1 /* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2015 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #ifndef SHRPX_MEMCACHED_CONNECTION_H 26 #define SHRPX_MEMCACHED_CONNECTION_H 27 28 #include "shrpx.h" 29 30 #include <memory> 31 #include <deque> 32 33 #include <ev.h> 34 35 #include "shrpx_connection.h" 36 #include "shrpx_tls.h" 37 #include "shrpx_connect_blocker.h" 38 #include "buffer.h" 39 #include "network.h" 40 41 using namespace nghttp2; 42 43 namespace shrpx { 44 45 struct MemcachedRequest; 46 enum class MemcachedOp : uint8_t; 47 enum class MemcachedStatusCode : uint16_t; 48 49 enum class MemcachedParseState { 50 HEADER24, 51 EXTRA, 52 VALUE, 53 }; 54 55 // Stores state when parsing response from memcached server 56 struct MemcachedParseContext { 57 // Buffer for value, dynamically allocated. 58 std::vector<uint8_t> value; 59 // cas in response 60 uint64_t cas; 61 // keylen in response 62 size_t keylen; 63 // extralen in response 64 size_t extralen; 65 // totalbody in response. The length of value is totalbody - 66 // extralen - keylen. 67 size_t totalbody; 68 // Number of bytes left to read variable length field. 69 size_t read_left; 70 // Parser state; see enum above 71 MemcachedParseState state; 72 // status_code in response 73 MemcachedStatusCode status_code; 74 // op in response 75 MemcachedOp op; 76 }; 77 78 struct MemcachedSendbuf { 79 // Buffer for header + extra + key 80 Buffer<512> headbuf; 81 // MemcachedRequest associated to this object 82 MemcachedRequest *req; 83 // Number of bytes left when sending value 84 size_t send_value_left; 85 // Returns the number of bytes this object transmits. leftMemcachedSendbuf86 size_t left() const { return headbuf.rleft() + send_value_left; } 87 }; 88 89 constexpr uint8_t MEMCACHED_REQ_MAGIC = 0x80; 90 constexpr uint8_t MEMCACHED_RES_MAGIC = 0x81; 91 92 // MemcachedConnection implements part of memcached binary protocol. 93 // This is not full brown implementation. Just the part we need is 94 // implemented. We only use GET and ADD. 95 // 96 // https://github.com/memcached/memcached/blob/master/doc/protocol-binary.xml 97 // https://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol 98 class MemcachedConnection { 99 public: 100 MemcachedConnection(const Address *addr, struct ev_loop *loop, 101 SSL_CTX *ssl_ctx, const StringRef &sni_name, 102 MemchunkPool *mcpool, std::mt19937 &gen); 103 ~MemcachedConnection(); 104 105 void disconnect(); 106 107 int add_request(std::unique_ptr<MemcachedRequest> req); 108 int initiate_connection(); 109 110 int connected(); 111 int on_write(); 112 int on_read(); 113 114 int write_clear(); 115 int read_clear(); 116 117 int tls_handshake(); 118 int write_tls(); 119 int read_tls(); 120 121 size_t fill_request_buffer(struct iovec *iov, size_t iovlen); 122 void drain_send_queue(size_t nwrite); 123 124 void make_request(MemcachedSendbuf *sendbuf, MemcachedRequest *req); 125 int parse_packet(); 126 size_t serialized_size(MemcachedRequest *req); 127 128 void signal_write(); 129 130 int noop(); 131 132 void reconnect_or_fail(); 133 134 private: 135 Connection conn_; 136 std::deque<std::unique_ptr<MemcachedRequest>> recvq_; 137 std::deque<std::unique_ptr<MemcachedRequest>> sendq_; 138 std::deque<MemcachedSendbuf> sendbufv_; 139 std::function<int(MemcachedConnection &)> do_read_, do_write_; 140 StringRef sni_name_; 141 tls::TLSSessionCache tls_session_cache_; 142 ConnectBlocker connect_blocker_; 143 MemcachedParseContext parse_state_; 144 const Address *addr_; 145 SSL_CTX *ssl_ctx_; 146 // Sum of the bytes to be transmitted in sendbufv_. 147 size_t sendsum_; 148 size_t try_count_; 149 bool connected_; 150 Buffer<8_k> recvbuf_; 151 }; 152 153 } // namespace shrpx 154 155 #endif // SHRPX_MEMCACHED_CONNECTION_H 156