12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2015 Tatsuhiro Tsujikawa
52c593315Sopenharmony_ci *
62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
122c593315Sopenharmony_ci * the following conditions:
132c593315Sopenharmony_ci *
142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
162c593315Sopenharmony_ci *
172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242c593315Sopenharmony_ci */
252c593315Sopenharmony_ci#ifndef SHRPX_MEMCACHED_CONNECTION_H
262c593315Sopenharmony_ci#define SHRPX_MEMCACHED_CONNECTION_H
272c593315Sopenharmony_ci
282c593315Sopenharmony_ci#include "shrpx.h"
292c593315Sopenharmony_ci
302c593315Sopenharmony_ci#include <memory>
312c593315Sopenharmony_ci#include <deque>
322c593315Sopenharmony_ci
332c593315Sopenharmony_ci#include <ev.h>
342c593315Sopenharmony_ci
352c593315Sopenharmony_ci#include "shrpx_connection.h"
362c593315Sopenharmony_ci#include "shrpx_tls.h"
372c593315Sopenharmony_ci#include "shrpx_connect_blocker.h"
382c593315Sopenharmony_ci#include "buffer.h"
392c593315Sopenharmony_ci#include "network.h"
402c593315Sopenharmony_ci
412c593315Sopenharmony_ciusing namespace nghttp2;
422c593315Sopenharmony_ci
432c593315Sopenharmony_cinamespace shrpx {
442c593315Sopenharmony_ci
452c593315Sopenharmony_cistruct MemcachedRequest;
462c593315Sopenharmony_cienum class MemcachedOp : uint8_t;
472c593315Sopenharmony_cienum class MemcachedStatusCode : uint16_t;
482c593315Sopenharmony_ci
492c593315Sopenharmony_cienum class MemcachedParseState {
502c593315Sopenharmony_ci  HEADER24,
512c593315Sopenharmony_ci  EXTRA,
522c593315Sopenharmony_ci  VALUE,
532c593315Sopenharmony_ci};
542c593315Sopenharmony_ci
552c593315Sopenharmony_ci// Stores state when parsing response from memcached server
562c593315Sopenharmony_cistruct MemcachedParseContext {
572c593315Sopenharmony_ci  // Buffer for value, dynamically allocated.
582c593315Sopenharmony_ci  std::vector<uint8_t> value;
592c593315Sopenharmony_ci  // cas in response
602c593315Sopenharmony_ci  uint64_t cas;
612c593315Sopenharmony_ci  // keylen in response
622c593315Sopenharmony_ci  size_t keylen;
632c593315Sopenharmony_ci  // extralen in response
642c593315Sopenharmony_ci  size_t extralen;
652c593315Sopenharmony_ci  // totalbody in response.  The length of value is totalbody -
662c593315Sopenharmony_ci  // extralen - keylen.
672c593315Sopenharmony_ci  size_t totalbody;
682c593315Sopenharmony_ci  // Number of bytes left to read variable length field.
692c593315Sopenharmony_ci  size_t read_left;
702c593315Sopenharmony_ci  // Parser state; see enum above
712c593315Sopenharmony_ci  MemcachedParseState state;
722c593315Sopenharmony_ci  // status_code in response
732c593315Sopenharmony_ci  MemcachedStatusCode status_code;
742c593315Sopenharmony_ci  // op in response
752c593315Sopenharmony_ci  MemcachedOp op;
762c593315Sopenharmony_ci};
772c593315Sopenharmony_ci
782c593315Sopenharmony_cistruct MemcachedSendbuf {
792c593315Sopenharmony_ci  // Buffer for header + extra + key
802c593315Sopenharmony_ci  Buffer<512> headbuf;
812c593315Sopenharmony_ci  // MemcachedRequest associated to this object
822c593315Sopenharmony_ci  MemcachedRequest *req;
832c593315Sopenharmony_ci  // Number of bytes left when sending value
842c593315Sopenharmony_ci  size_t send_value_left;
852c593315Sopenharmony_ci  // Returns the number of bytes this object transmits.
862c593315Sopenharmony_ci  size_t left() const { return headbuf.rleft() + send_value_left; }
872c593315Sopenharmony_ci};
882c593315Sopenharmony_ci
892c593315Sopenharmony_ciconstexpr uint8_t MEMCACHED_REQ_MAGIC = 0x80;
902c593315Sopenharmony_ciconstexpr uint8_t MEMCACHED_RES_MAGIC = 0x81;
912c593315Sopenharmony_ci
922c593315Sopenharmony_ci// MemcachedConnection implements part of memcached binary protocol.
932c593315Sopenharmony_ci// This is not full brown implementation.  Just the part we need is
942c593315Sopenharmony_ci// implemented.  We only use GET and ADD.
952c593315Sopenharmony_ci//
962c593315Sopenharmony_ci// https://github.com/memcached/memcached/blob/master/doc/protocol-binary.xml
972c593315Sopenharmony_ci// https://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol
982c593315Sopenharmony_ciclass MemcachedConnection {
992c593315Sopenharmony_cipublic:
1002c593315Sopenharmony_ci  MemcachedConnection(const Address *addr, struct ev_loop *loop,
1012c593315Sopenharmony_ci                      SSL_CTX *ssl_ctx, const StringRef &sni_name,
1022c593315Sopenharmony_ci                      MemchunkPool *mcpool, std::mt19937 &gen);
1032c593315Sopenharmony_ci  ~MemcachedConnection();
1042c593315Sopenharmony_ci
1052c593315Sopenharmony_ci  void disconnect();
1062c593315Sopenharmony_ci
1072c593315Sopenharmony_ci  int add_request(std::unique_ptr<MemcachedRequest> req);
1082c593315Sopenharmony_ci  int initiate_connection();
1092c593315Sopenharmony_ci
1102c593315Sopenharmony_ci  int connected();
1112c593315Sopenharmony_ci  int on_write();
1122c593315Sopenharmony_ci  int on_read();
1132c593315Sopenharmony_ci
1142c593315Sopenharmony_ci  int write_clear();
1152c593315Sopenharmony_ci  int read_clear();
1162c593315Sopenharmony_ci
1172c593315Sopenharmony_ci  int tls_handshake();
1182c593315Sopenharmony_ci  int write_tls();
1192c593315Sopenharmony_ci  int read_tls();
1202c593315Sopenharmony_ci
1212c593315Sopenharmony_ci  size_t fill_request_buffer(struct iovec *iov, size_t iovlen);
1222c593315Sopenharmony_ci  void drain_send_queue(size_t nwrite);
1232c593315Sopenharmony_ci
1242c593315Sopenharmony_ci  void make_request(MemcachedSendbuf *sendbuf, MemcachedRequest *req);
1252c593315Sopenharmony_ci  int parse_packet();
1262c593315Sopenharmony_ci  size_t serialized_size(MemcachedRequest *req);
1272c593315Sopenharmony_ci
1282c593315Sopenharmony_ci  void signal_write();
1292c593315Sopenharmony_ci
1302c593315Sopenharmony_ci  int noop();
1312c593315Sopenharmony_ci
1322c593315Sopenharmony_ci  void reconnect_or_fail();
1332c593315Sopenharmony_ci
1342c593315Sopenharmony_ciprivate:
1352c593315Sopenharmony_ci  Connection conn_;
1362c593315Sopenharmony_ci  std::deque<std::unique_ptr<MemcachedRequest>> recvq_;
1372c593315Sopenharmony_ci  std::deque<std::unique_ptr<MemcachedRequest>> sendq_;
1382c593315Sopenharmony_ci  std::deque<MemcachedSendbuf> sendbufv_;
1392c593315Sopenharmony_ci  std::function<int(MemcachedConnection &)> do_read_, do_write_;
1402c593315Sopenharmony_ci  StringRef sni_name_;
1412c593315Sopenharmony_ci  tls::TLSSessionCache tls_session_cache_;
1422c593315Sopenharmony_ci  ConnectBlocker connect_blocker_;
1432c593315Sopenharmony_ci  MemcachedParseContext parse_state_;
1442c593315Sopenharmony_ci  const Address *addr_;
1452c593315Sopenharmony_ci  SSL_CTX *ssl_ctx_;
1462c593315Sopenharmony_ci  // Sum of the bytes to be transmitted in sendbufv_.
1472c593315Sopenharmony_ci  size_t sendsum_;
1482c593315Sopenharmony_ci  size_t try_count_;
1492c593315Sopenharmony_ci  bool connected_;
1502c593315Sopenharmony_ci  Buffer<8_k> recvbuf_;
1512c593315Sopenharmony_ci};
1522c593315Sopenharmony_ci
1532c593315Sopenharmony_ci} // namespace shrpx
1542c593315Sopenharmony_ci
1552c593315Sopenharmony_ci#endif // SHRPX_MEMCACHED_CONNECTION_H
156