libcouchbase 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/.gitignore +2 -0
  3. data/ext/libcouchbase/CMakeLists.txt +5 -7
  4. data/ext/libcouchbase/README.markdown +2 -2
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +49 -0
  6. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  7. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
  8. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +2 -1
  9. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  10. data/ext/libcouchbase/cmake/config-cmake.h.in +2 -0
  11. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  12. data/ext/libcouchbase/cmake/source_files.cmake +34 -14
  13. data/ext/libcouchbase/configure.pl +1 -1
  14. data/ext/libcouchbase/contrib/genhash/genhash.h +6 -0
  15. data/ext/libcouchbase/include/libcouchbase/auth.h +10 -0
  16. data/ext/libcouchbase/include/libcouchbase/couchbase.h +10 -0
  17. data/ext/libcouchbase/include/libcouchbase/error.h +7 -0
  18. data/ext/libcouchbase/include/libcouchbase/n1ql.h +13 -1
  19. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +1 -1
  20. data/ext/libcouchbase/include/libcouchbase/subdoc.h +9 -0
  21. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  22. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  23. data/ext/libcouchbase/include/memcached/protocol_binary.h +21 -1132
  24. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  25. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  26. data/ext/libcouchbase/src/README.md +0 -2
  27. data/ext/libcouchbase/src/auth-priv.h +1 -0
  28. data/ext/libcouchbase/src/auth.cc +10 -0
  29. data/ext/libcouchbase/src/bootstrap.cc +216 -0
  30. data/ext/libcouchbase/src/bootstrap.h +50 -39
  31. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +455 -0
  32. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  33. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +528 -0
  34. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  35. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.cc +115 -0
  36. data/ext/libcouchbase/src/bucketconfig/clconfig.h +407 -386
  37. data/ext/libcouchbase/src/bucketconfig/confmon.cc +378 -0
  38. data/ext/libcouchbase/src/cbft.cc +22 -27
  39. data/ext/libcouchbase/src/cntl.cc +24 -24
  40. data/ext/libcouchbase/src/connspec.cc +30 -1
  41. data/ext/libcouchbase/src/connspec.h +17 -0
  42. data/ext/libcouchbase/src/dns-srv.cc +143 -0
  43. data/ext/libcouchbase/src/{dump.c → dump.cc} +8 -11
  44. data/ext/libcouchbase/src/getconfig.cc +73 -0
  45. data/ext/libcouchbase/src/handler.cc +84 -85
  46. data/ext/libcouchbase/src/hostlist.cc +0 -1
  47. data/ext/libcouchbase/src/hostlist.h +6 -1
  48. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  49. data/ext/libcouchbase/src/http/http.cc +9 -29
  50. data/ext/libcouchbase/src/http/http.h +1 -34
  51. data/ext/libcouchbase/src/http/http_io.cc +22 -26
  52. data/ext/libcouchbase/src/instance.cc +102 -28
  53. data/ext/libcouchbase/src/internal.h +47 -29
  54. data/ext/libcouchbase/src/jsparse/parser.cc +146 -202
  55. data/ext/libcouchbase/src/jsparse/parser.h +91 -98
  56. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  57. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  58. data/ext/libcouchbase/src/lcbio/connect.cc +562 -0
  59. data/ext/libcouchbase/src/lcbio/connect.h +9 -2
  60. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  61. data/ext/libcouchbase/src/lcbio/iotable.h +61 -16
  62. data/ext/libcouchbase/src/lcbio/ioutils.h +1 -1
  63. data/ext/libcouchbase/src/lcbio/manager.c +2 -2
  64. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  65. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  66. data/ext/libcouchbase/src/mcserver/mcserver.cc +723 -0
  67. data/ext/libcouchbase/src/mcserver/mcserver.h +160 -70
  68. data/ext/libcouchbase/src/mcserver/negotiate.cc +118 -152
  69. data/ext/libcouchbase/src/mcserver/negotiate.h +85 -74
  70. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  71. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  72. data/ext/libcouchbase/src/n1ql/n1ql.cc +56 -32
  73. data/ext/libcouchbase/src/{newconfig.c → newconfig.cc} +42 -70
  74. data/ext/libcouchbase/src/nodeinfo.cc +4 -8
  75. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  76. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  77. data/ext/libcouchbase/src/operations/{durability-cas.c → durability-cas.cc} +92 -76
  78. data/ext/libcouchbase/src/operations/{durability-seqno.c → durability-seqno.cc} +55 -49
  79. data/ext/libcouchbase/src/operations/durability.cc +643 -0
  80. data/ext/libcouchbase/src/operations/durability_internal.h +212 -124
  81. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  82. data/ext/libcouchbase/src/operations/{observe-seqno.c → observe-seqno.cc} +5 -8
  83. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +69 -94
  84. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  85. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  86. data/ext/libcouchbase/src/operations/{stats.c → stats.cc} +66 -78
  87. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  88. data/ext/libcouchbase/src/operations/subdoc.cc +38 -18
  89. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  90. data/ext/libcouchbase/src/packetutils.h +200 -137
  91. data/ext/libcouchbase/src/probes.d +1 -1
  92. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +3 -4
  93. data/ext/libcouchbase/src/retryq.cc +394 -0
  94. data/ext/libcouchbase/src/retryq.h +116 -104
  95. data/ext/libcouchbase/src/settings.h +2 -1
  96. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  97. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  98. data/ext/libcouchbase/src/trace.h +8 -8
  99. data/ext/libcouchbase/src/vbucket/vbucket.c +0 -1
  100. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  101. data/ext/libcouchbase/src/views/docreq.h +24 -30
  102. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  103. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  104. data/ext/libcouchbase/src/{wait.c → wait.cc} +12 -17
  105. data/ext/libcouchbase/tests/basic/t_connstr.cc +89 -50
  106. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -78
  107. data/ext/libcouchbase/tests/basic/t_packet.cc +35 -42
  108. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  109. data/ext/libcouchbase/tests/iotests/t_confmon.cc +94 -111
  110. data/ext/libcouchbase/tests/iotests/t_sched.cc +1 -2
  111. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  112. data/ext/libcouchbase/tools/cbc-pillowfight.cc +1 -1
  113. data/lib/libcouchbase/version.rb +1 -1
  114. metadata +36 -39
  115. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  116. data/ext/libcouchbase/src/bootstrap.c +0 -269
  117. data/ext/libcouchbase/src/bucketconfig/bc_cccp.c +0 -495
  118. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  119. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  120. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  121. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  122. data/ext/libcouchbase/src/getconfig.c +0 -100
  123. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  124. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  125. data/ext/libcouchbase/src/mcserver/mcserver.c +0 -784
  126. data/ext/libcouchbase/src/operations/durability.c +0 -668
  127. data/ext/libcouchbase/src/packetutils.c +0 -60
  128. data/ext/libcouchbase/src/retryq.c +0 -424
  129. data/ext/libcouchbase/src/simplestring.c +0 -211
  130. data/ext/libcouchbase/src/simplestring.h +0 -228
  131. data/ext/libcouchbase/src/ssobuf.h +0 -82
  132. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  133. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -24,98 +24,188 @@
24
24
  #include <netbuf/netbuf.h>
25
25
 
26
26
  #ifdef __cplusplus
27
- extern "C" {
28
- #endif
27
+ namespace lcb {
29
28
 
30
- struct lcb_settings_st;
31
- struct lcb_server_st;
29
+ class RetryQueue;
30
+ struct RetryOp;
32
31
 
33
32
  /**
34
33
  * The structure representing each couchbase server
35
34
  */
36
- typedef struct mc_SERVER_st {
37
- /** Pipeline object for command queues */
38
- mc_PIPELINE pipeline;
35
+ class Server : public mc_PIPELINE {
36
+ public:
37
+ /**
38
+ * Allocate and initialize a new server object. The object will not be
39
+ * connected
40
+ * @param instance the instance to which the server belongs
41
+ * @param ix the server index in the configuration
42
+ */
43
+ Server(lcb_t, int);
44
+
45
+ /**
46
+ * Close the server. The resources of the server may still continue to persist
47
+ * internally for a bit until all callbacks have been delivered and all buffers
48
+ * flushed and/or failed.
49
+ */
50
+ void close();
51
+
52
+ /**
53
+ * Schedule a flush and potentially flush some immediate data on the server.
54
+ * This is safe to call multiple times, however performance considerations
55
+ * should be taken into account
56
+ */
57
+ void flush();
58
+
59
+ /**
60
+ * Wrapper around mcreq_pipeline_timeout() and/or mcreq_pipeline_fail(). This
61
+ * function will purge all pending requests within the server and invoke
62
+ * their callbacks with the given error code passed as `err`. Depending on
63
+ * the error code, some operations may be retried.
64
+ *
65
+ * @param err the error code by which to fail the commands
66
+ *
67
+ * @note This function does not modify the server's socket or state in itself,
68
+ * but rather simply wipes the commands from its queue
69
+ */
70
+ void purge(lcb_error_t err) {
71
+ purge(err, 0, NULL, Server::REFRESH_NEVER);
72
+ }
73
+
74
+ /** Callback for mc_pipeline_fail_chain */
75
+ inline void purge_single(mc_PACKET*, lcb_error_t);
76
+
77
+ /**
78
+ * Returns true or false depending on whether there are pending commands on
79
+ * this server
80
+ */
81
+ bool has_pending() const {
82
+ return !SLLIST_IS_EMPTY(&requests);
83
+ }
84
+
85
+ int get_index() const {
86
+ return mc_PIPELINE::index;
87
+ }
88
+
89
+ lcb_t get_instance() const {
90
+ return instance;
91
+ }
92
+
93
+ const lcb_settings* get_settings() const {
94
+ return settings;
95
+ }
96
+
97
+ void set_new_index(int new_index) {
98
+ mc_PIPELINE::index = new_index;
99
+ }
100
+
101
+ const lcb_host_t& get_host() const {
102
+ return *curhost;
103
+ }
104
+
105
+ bool supports_mutation_tokens() const {
106
+ return mutation_tokens;
107
+ }
108
+
109
+ bool supports_compression() const {
110
+ return compsupport;
111
+ }
112
+
113
+ bool is_connected() const {
114
+ return connctx != NULL;
115
+ }
116
+
117
+ /** "Temporary" constructor. Only for use in retry queue */
118
+ Server();
119
+ ~Server();
120
+
121
+ enum State {
122
+ /* There are no known errored commands on this server */
123
+ S_CLEAN,
124
+
125
+ /* In the process of draining remaining commands to be flushed. The commands
126
+ * being drained may have already been rescheduled to another server or
127
+ * placed inside the error queue, but are pending being flushed. This will
128
+ * only happen in completion-style I/O plugins. When this state is in effect,
129
+ * subsequent attempts to connect will be blocked until all commands have
130
+ * been properly drained.
131
+ */
132
+ S_ERRDRAIN,
133
+
134
+ /* The server object has been closed, either because it has been removed
135
+ * from the cluster or because the related lcb_t has been destroyed.
136
+ */
137
+ S_CLOSED,
138
+
139
+ /*
140
+ * Server has been temporarily constructed.
141
+ */
142
+ S_TEMPORARY
143
+ };
144
+
145
+ static Server* get(lcbio_CTX *ctx) {
146
+ return reinterpret_cast<Server*>(lcbio_ctx_data(ctx));
147
+ }
148
+
149
+ uint32_t default_timeout() const {
150
+ return settings->operation_timeout;
151
+ }
152
+
153
+ uint32_t next_timeout() const;
154
+
155
+ bool check_closed();
156
+ void start_errored_ctx(State next_state);
157
+ void finalize_errored_ctx();
158
+ void socket_failed(lcb_error_t);
159
+ void io_timeout();
160
+
161
+ enum RefreshPolicy {
162
+ REFRESH_ALWAYS,
163
+ REFRESH_ONFAILED,
164
+ REFRESH_NEVER
165
+ };
166
+
167
+ int purge(lcb_error_t error, hrtime_t thresh, hrtime_t *next,
168
+ RefreshPolicy policy);
169
+
170
+ void connect();
171
+
172
+ void handle_connected(lcbio_SOCKET *socket, lcb_error_t err, lcbio_OSERR syserr);
173
+
174
+ enum ReadState {
175
+ PKT_READ_COMPLETE,
176
+ PKT_READ_PARTIAL
177
+ };
178
+
179
+ ReadState try_read(lcbio_CTX *ctx, rdb_IOROPE *ior);
180
+ bool handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt);
181
+ bool maybe_retry_packet(mc_PACKET *pkt, lcb_error_t err);
182
+ bool maybe_reconnect_on_fake_timeout(lcb_error_t received_error);
183
+
184
+ /** Disable */
185
+ Server(const Server&);
186
+
187
+ State state;
188
+
189
+ /** IO/Operation timer */
190
+ lcbio_pTIMER io_timer;
39
191
 
40
192
  /** Pointer back to the instance */
41
193
  lcb_t instance;
42
194
 
43
195
  lcb_settings *settings;
44
196
 
45
- /* Defined in mcserver.c */
46
- int state;
47
-
48
197
  /** Whether compression is supported */
49
198
  short compsupport;
50
199
 
51
200
  /** Whether extended 'UUID' and 'seqno' are available for each mutation */
52
201
  short mutation_tokens;
53
202
 
54
- /** IO/Operation timer */
55
- lcbio_pTIMER io_timer;
56
-
57
203
  lcbio_CTX *connctx;
58
204
  lcbio_CONNREQ connreq;
59
205
 
60
206
  /** Request for current connection */
61
207
  lcb_host_t *curhost;
62
- } mc_SERVER;
63
-
64
- #define MCSERVER_TIMEOUT(c) (c)->settings->operation_timeout
65
-
66
- /**
67
- * Allocate and initialize a new server object. The object will not be
68
- * connected
69
- * @param instance the instance to which the server belongs
70
- * @param ix the server index in the configuration
71
- * @return the new object or NULL on allocation failure.
72
- */
73
- mc_SERVER *
74
- mcserver_alloc(lcb_t instance, int ix);
75
-
76
- /**
77
- * Close the server. The resources of the server may still continue to persist
78
- * internally for a bit until all callbacks have been delivered and all buffers
79
- * flushed and/or failed.
80
- * @param server the server to release
81
- */
82
- void
83
- mcserver_close(mc_SERVER *server);
84
-
85
- /**
86
- * Schedule a flush and potentially flush some immediate data on the server.
87
- * This is safe to call multiple times, however performance considerations
88
- * should be taken into account
89
- */
90
- void
91
- mcserver_flush(mc_SERVER *server);
92
-
93
- /**
94
- * Wrapper around mcreq_pipeline_timeout() and/or mcreq_pipeline_fail(). This
95
- * function will purge all pending requests within the server and invoke
96
- * their callbacks with the given error code passed as `err`. Depending on
97
- * the error code, some operations may be retried.
98
- * @param server the server to fail
99
- * @param err the error code by which to fail the commands
100
- *
101
- * @note This function does not modify the server's socket or state in itself,
102
- * but rather simply wipes the commands from its queue
103
- */
104
- void
105
- mcserver_fail_chain(mc_SERVER *server, lcb_error_t err);
106
-
107
- /**
108
- * Returns true or false depending on whether there are pending commands on
109
- * this server
110
- */
111
- LCB_INTERNAL_API
112
- int
113
- mcserver_has_pending(mc_SERVER *server);
114
-
115
- #define mcserver_get_host(server) (server)->curhost->host
116
- #define mcserver_get_port(server) (server)->curhost->port
117
-
118
- #ifdef __cplusplus
208
+ };
119
209
  }
120
210
  #endif /* __cplusplus */
121
211
  #endif /* LCB_MCSERVER_H */
@@ -15,6 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
+ #include <algorithm>
18
19
  #include "packetutils.h"
19
20
  #include "mcserver.h"
20
21
  #include "logging.h"
@@ -26,47 +27,13 @@
26
27
  #include "negotiate.h"
27
28
  #include "ctx-log-inl.h"
28
29
 
29
- #include <string>
30
- #include <sstream>
31
- #include <vector>
30
+ using namespace lcb;
32
31
 
33
- #define LOGARGS(ctx, lvl) ctx->sasl->settings, "negotiation", LCB_LOG_##lvl, __FILE__, __LINE__
34
- static void cleanup_negotiated(mc_pSESSINFO info);
32
+ #define LOGARGS(ctx, lvl) ctx->settings, "negotiation", LCB_LOG_##lvl, __FILE__, __LINE__
33
+ static void cleanup_negotiated(SessionInfo* info);
35
34
  static void handle_ioerr(lcbio_CTX *ctx, lcb_error_t err);
36
- static void handle_read(lcbio_CTX *ioctx, unsigned);
37
35
  #define SESSREQ_LOGFMT "<%s:%s> (SASLREQ=%p) "
38
36
 
39
- /**
40
- * Inner negotiation structure which is maintained as part of a 'protocol
41
- * context'.
42
- */
43
- struct mc_SESSINFO : public lcbio_PROTOCTX {
44
- union {
45
- cbsasl_secret_t secret;
46
- char buffer[256];
47
- } u_auth;
48
-
49
- static mc_SESSINFO *get(void *arg) {
50
- return reinterpret_cast<mc_SESSINFO*>(arg);
51
- }
52
-
53
- mc_SESSINFO(lcb_settings *settings_);
54
- bool setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
55
- const lcb::Authenticator& auth);
56
-
57
- ~mc_SESSINFO() {
58
- if (sasl_client != NULL) {
59
- cbsasl_dispose(&sasl_client);
60
- sasl_client = NULL;
61
- }
62
- }
63
-
64
- cbsasl_conn_t *sasl_client;
65
- std::string mech;
66
- std::vector<uint16_t> server_features;
67
- lcb_settings *settings;
68
- };
69
-
70
37
  static void timeout_handler(void *arg);
71
38
 
72
39
  #define SESSREQ_LOGID(s) get_ctx_host(s->ctx), get_ctx_port(s->ctx), (void*)s
@@ -84,28 +51,37 @@ close_cb(lcbio_SOCKET *s, int reusable, void *arg)
84
51
  * of the request for negotiation and is deleted once negotiation has
85
52
  * completed (or failed).
86
53
  */
87
- struct mc_SESSREQ {
88
- static mc_SESSREQ *get(void *arg) {
89
- return reinterpret_cast<mc_SESSREQ*>(arg);
54
+ class lcb::SessionRequestImpl : public SessionRequest {
55
+ public:
56
+ static SessionRequestImpl *get(void *arg) {
57
+ return reinterpret_cast<SessionRequestImpl*>(arg);
90
58
  }
91
59
 
92
- void start(lcbio_SOCKET *sock, lcb_settings *settings);
60
+ bool setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
61
+ const lcb::Authenticator& auth);
62
+ void start(lcbio_SOCKET *sock);
93
63
  bool send_hello();
94
64
  bool send_step(const lcb::MemcachedResponse& packet);
95
65
  bool read_hello(const lcb::MemcachedResponse& packet);
66
+ void send_auth(const char *sasl_data, unsigned ndata);
67
+ void handle_read(lcbio_CTX *ioctx);
68
+
69
+ enum MechStatus { MECH_UNAVAILABLE, MECH_NOT_NEEDED, MECH_OK };
70
+ MechStatus set_chosen_mech(std::string& mechlist, const char **data, unsigned int *ndata);
96
71
 
97
- mc_SESSREQ(lcbio_CONNDONE_cb callback, void *data, uint32_t timeout,
98
- lcbio_TABLE *iot)
72
+ SessionRequestImpl(lcbio_CONNDONE_cb callback, void *data, uint32_t timeout, lcbio_TABLE *iot, lcb_settings* settings_)
99
73
  : ctx(NULL), cb(callback), cbdata(data),
100
74
  timer(lcbio_timer_new(iot, this, timeout_handler)),
101
- last_err(LCB_SUCCESS), sasl(NULL) {
75
+ last_err(LCB_SUCCESS), info(NULL),
76
+ settings(settings_) {
102
77
 
103
78
  if (timeout) {
104
79
  lcbio_timer_rearm(timer, timeout);
105
80
  }
81
+ memset(&u_auth, 0, sizeof(u_auth));
106
82
  }
107
83
 
108
- ~mc_SESSREQ();
84
+ virtual ~SessionRequestImpl();
109
85
 
110
86
  void cancel() {
111
87
  cb = NULL;
@@ -132,8 +108,8 @@ struct mc_SESSREQ {
132
108
  lcbio_ctx_close(ctx, close_cb, &s);
133
109
  ctx = NULL;
134
110
 
135
- lcbio_protoctx_add(s, sasl);
136
- sasl = NULL;
111
+ lcbio_protoctx_add(s, info);
112
+ info = NULL;
137
113
 
138
114
  /** Invoke the callback, marking it a success */
139
115
  cb(s, cbdata, LCB_SUCCESS, 0);
@@ -153,19 +129,29 @@ struct mc_SESSREQ {
153
129
  return last_err != LCB_SUCCESS;
154
130
  }
155
131
 
132
+ union {
133
+ cbsasl_secret_t secret;
134
+ char buffer[256];
135
+ } u_auth;
136
+
156
137
  lcbio_CTX *ctx;
157
138
  lcbio_CONNDONE_cb cb;
158
139
  void *cbdata;
159
140
  lcbio_pTIMER timer;
160
141
  lcb_error_t last_err;
161
- mc_pSESSINFO sasl;
142
+ cbsasl_conn_t *sasl_client;
143
+ SessionInfo* info;
144
+ lcb_settings *settings;
162
145
  };
163
146
 
147
+ static void handle_read(lcbio_CTX *ioctx, unsigned) {
148
+ SessionRequestImpl::get(lcbio_ctx_data(ioctx))->handle_read(ioctx);
149
+ }
164
150
 
165
151
  static int
166
152
  sasl_get_username(void *context, int id, const char **result, unsigned int *len)
167
153
  {
168
- mc_SESSINFO *ctx = mc_SESSINFO::get(context);
154
+ SessionRequestImpl *ctx = SessionRequestImpl::get(context);
169
155
  const char *u = NULL, *p = NULL;
170
156
  if (!context || !result || (id != CBSASL_CB_USER && id != CBSASL_CB_AUTHNAME)) {
171
157
  return SASL_BADPARAM;
@@ -184,7 +170,7 @@ static int
184
170
  sasl_get_password(cbsasl_conn_t *conn, void *context, int id,
185
171
  cbsasl_secret_t **psecret)
186
172
  {
187
- struct mc_SESSINFO *ctx = mc_SESSINFO::get(context);
173
+ SessionRequestImpl *ctx = SessionRequestImpl::get(context);
188
174
  if (!conn || ! psecret || id != CBSASL_CB_PASS || ctx == NULL) {
189
175
  return SASL_BADPARAM;
190
176
  }
@@ -193,19 +179,14 @@ sasl_get_password(cbsasl_conn_t *conn, void *context, int id,
193
179
  return SASL_OK;
194
180
  }
195
181
 
196
- mc_SESSINFO::mc_SESSINFO(lcb_settings *settings_)
182
+ SessionInfo::SessionInfo()
197
183
  {
198
- sasl_client = NULL;
199
- memset(&u_auth, 0, sizeof(u_auth));
200
-
201
184
  lcbio_PROTOCTX::id = LCBIO_PROTOCTX_SESSINFO;
202
- lcbio_PROTOCTX::dtor = (void (*)(struct lcbio_PROTOCTX *))cleanup_negotiated;
203
-
204
- settings = settings_;
185
+ lcbio_PROTOCTX::dtor = (void (*)(lcbio_PROTOCTX *))cleanup_negotiated;
205
186
  }
206
187
 
207
188
  bool
208
- mc_SESSINFO::setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
189
+ SessionRequestImpl::setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
209
190
  const lcb::Authenticator& auth)
210
191
  {
211
192
  cbsasl_callback_t sasl_callbacks[4];
@@ -251,7 +232,7 @@ mc_SESSINFO::setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
251
232
  static void
252
233
  timeout_handler(void *arg)
253
234
  {
254
- mc_pSESSREQ sreq = mc_SESSREQ::get(arg);
235
+ SessionRequestImpl *sreq = SessionRequestImpl::get(arg);
255
236
  sreq->fail(LCB_ETIMEDOUT, "Negotiation timed out");
256
237
  }
257
238
 
@@ -260,66 +241,62 @@ timeout_handler(void *arg)
260
241
  * @return 0 to continue authentication, 1 if no authentication needed, or
261
242
  * -1 on error.
262
243
  */
263
- static int
264
- set_chosen_mech(mc_pSESSREQ sreq, std::string& mechlist,
244
+ SessionRequestImpl::MechStatus
245
+ SessionRequestImpl::set_chosen_mech(std::string& mechlist,
265
246
  const char **data, unsigned int *ndata)
266
247
  {
267
248
  cbsasl_error_t saslerr;
268
- mc_pSESSINFO ctx = sreq->sasl;
269
-
270
- if (ctx->settings->sasl_mech_force) {
271
- char *forcemech = ctx->settings->sasl_mech_force;
249
+ if (settings->sasl_mech_force) {
250
+ char *forcemech = settings->sasl_mech_force;
272
251
  if (mechlist.find(forcemech) == std::string::npos) {
273
252
  /** Requested mechanism not found */
274
- sreq->set_error(LCB_SASLMECH_UNAVAILABLE, mechlist.c_str());
275
- return -1;
253
+ set_error(LCB_SASLMECH_UNAVAILABLE, mechlist.c_str());
254
+ return MECH_UNAVAILABLE;
276
255
  }
277
256
  mechlist.assign(forcemech);
278
257
  }
279
258
 
280
259
  const char *chosenmech;
281
- saslerr = cbsasl_client_start(ctx->sasl_client, mechlist.c_str(),
260
+ saslerr = cbsasl_client_start(sasl_client, mechlist.c_str(),
282
261
  NULL, data, ndata, &chosenmech);
283
262
  switch (saslerr) {
284
263
  case SASL_OK:
285
- ctx->mech.assign(chosenmech);
286
- return 0;
264
+ info->mech.assign(chosenmech);
265
+ return MECH_OK;
287
266
  case SASL_NOMECH:
288
- lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "Server does not support SASL (no mechanisms supported)", SESSREQ_LOGID(sreq));
289
- return 1;
267
+ lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "Server does not support SASL (no mechanisms supported)", SESSREQ_LOGID(this));
268
+ return MECH_NOT_NEEDED;
290
269
  break;
291
270
  default:
292
- lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "cbsasl_client_start returned %d", SESSREQ_LOGID(sreq), saslerr);
293
- sreq->set_error(LCB_EINTERNAL, "Couldn't start SASL client");
294
- return -1;
271
+ lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "cbsasl_client_start returned %d", SESSREQ_LOGID(this), saslerr);
272
+ set_error(LCB_EINTERNAL, "Couldn't start SASL client");
273
+ return MECH_UNAVAILABLE;
295
274
  }
296
275
  }
297
276
 
298
277
  /**
299
278
  * Given the specific mechanisms, send the auth packet to the server.
300
279
  */
301
- static int
302
- send_sasl_auth(mc_SESSREQ *pend, const char *sasl_data, unsigned ndata)
280
+ void
281
+ SessionRequestImpl::send_auth(const char *sasl_data, unsigned ndata)
303
282
  {
304
- mc_pSESSINFO ctx = pend->sasl;
305
283
  lcb::MemcachedRequest hdr(PROTOCOL_BINARY_CMD_SASL_AUTH);
306
- hdr.sizes(0, ctx->mech.size(), ndata);
284
+ hdr.sizes(0, info->mech.size(), ndata);
307
285
 
308
- lcbio_ctx_put(pend->ctx, hdr.data(), hdr.size());
309
- lcbio_ctx_put(pend->ctx, ctx->mech.c_str(), ctx->mech.size());
310
- lcbio_ctx_put(pend->ctx, sasl_data, ndata);
311
- lcbio_ctx_rwant(pend->ctx, 24);
312
- return 0;
286
+ lcbio_ctx_put(ctx, hdr.data(), hdr.size());
287
+ lcbio_ctx_put(ctx, info->mech.c_str(), info->mech.size());
288
+ lcbio_ctx_put(ctx, sasl_data, ndata);
289
+ lcbio_ctx_rwant(ctx, 24);
313
290
  }
314
291
 
315
292
  bool
316
- mc_SESSREQ::send_step(const lcb::MemcachedResponse& packet)
293
+ SessionRequestImpl::send_step(const lcb::MemcachedResponse& packet)
317
294
  {
318
295
  cbsasl_error_t saslerr;
319
296
  const char *step_data;
320
297
  unsigned int ndata;
321
298
 
322
- saslerr = cbsasl_client_step(sasl->sasl_client,
299
+ saslerr = cbsasl_client_step(sasl_client,
323
300
  packet.body<const char*>(), packet.bodylen(), NULL, &step_data, &ndata);
324
301
 
325
302
  if (saslerr != SASL_CONTINUE) {
@@ -328,9 +305,9 @@ mc_SESSREQ::send_step(const lcb::MemcachedResponse& packet)
328
305
  }
329
306
 
330
307
  lcb::MemcachedRequest hdr(PROTOCOL_BINARY_CMD_SASL_STEP);
331
- hdr.sizes(0, sasl->mech.size(), ndata);
308
+ hdr.sizes(0, info->mech.size(), ndata);
332
309
  lcbio_ctx_put(ctx, hdr.data(), hdr.size());
333
- lcbio_ctx_put(ctx, sasl->mech.c_str(), sasl->mech.size());
310
+ lcbio_ctx_put(ctx, info->mech.c_str(), info->mech.size());
334
311
  lcbio_ctx_put(ctx, step_data, ndata);
335
312
  lcbio_ctx_rwant(ctx, 24);
336
313
  return true;
@@ -340,13 +317,13 @@ mc_SESSREQ::send_step(const lcb::MemcachedResponse& packet)
340
317
  #define LCB_HELLO_DEFL_LENGTH (sizeof(LCB_HELLO_DEFL_STRING)-1)
341
318
 
342
319
  bool
343
- mc_SESSREQ::send_hello()
320
+ SessionRequestImpl::send_hello()
344
321
  {
345
- const lcb_settings *settings = sasl->settings;
346
322
  lcb_U16 features[MEMCACHED_TOTAL_HELLO_FEATURES];
347
323
 
348
324
  unsigned nfeatures = 0;
349
325
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TLS;
326
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_XATTR;
350
327
  if (settings->tcp_nodelay) {
351
328
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TCPNODELAY;
352
329
  }
@@ -388,7 +365,7 @@ mc_SESSREQ::send_hello()
388
365
  }
389
366
 
390
367
  bool
391
- mc_SESSREQ::read_hello(const lcb::MemcachedResponse& resp)
368
+ SessionRequestImpl::read_hello(const lcb::MemcachedResponse& resp)
392
369
  {
393
370
  /* some caps */
394
371
  const char *cur;
@@ -398,8 +375,8 @@ mc_SESSREQ::read_hello(const lcb::MemcachedResponse& resp)
398
375
  lcb_U16 tmp;
399
376
  memcpy(&tmp, cur, sizeof(tmp));
400
377
  tmp = ntohs(tmp);
401
- lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Found feature 0x%x (%s)", SESSREQ_LOGID(this), tmp, protocol_feature_2_text(tmp));
402
- sasl->server_features.push_back(tmp);
378
+ lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server supports feature: 0x%x (%s)", SESSREQ_LOGID(this), tmp, protocol_feature_2_text(tmp));
379
+ info->server_features.push_back(tmp);
403
380
  }
404
381
  return true;
405
382
  }
@@ -415,10 +392,9 @@ typedef enum {
415
392
  * It's assumed the server buffers will be reset upon close(), so we must make
416
393
  * sure to _not_ release the ringbuffer if that happens.
417
394
  */
418
- static void
419
- handle_read(lcbio_CTX *ioctx, unsigned)
395
+ void
396
+ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
420
397
  {
421
- mc_pSESSREQ sreq = mc_SESSREQ::get(lcbio_ctx_data(ioctx));
422
398
  lcb::MemcachedResponse resp;
423
399
  unsigned required;
424
400
  sreq_STATE state = SREQ_S_WAIT;
@@ -433,20 +409,15 @@ handle_read(lcbio_CTX *ioctx, unsigned)
433
409
 
434
410
  switch (resp.opcode()) {
435
411
  case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: {
436
- int mechrc;
437
412
  const char *mechlist_data;
438
413
  unsigned int nmechlist_data;
439
414
  std::string mechs(resp.body<const char*>(), resp.bodylen());
440
415
 
441
- mechrc = set_chosen_mech(sreq, mechs, &mechlist_data, &nmechlist_data);
442
- if (mechrc == 0) {
443
- if (0 == send_sasl_auth(sreq, mechlist_data, nmechlist_data)) {
444
- state = SREQ_S_WAIT;
445
- } else {
446
- state = SREQ_S_ERROR;
447
- }
448
-
449
- } else if (mechrc < 0) {
416
+ MechStatus mechrc = set_chosen_mech(mechs, &mechlist_data, &nmechlist_data);
417
+ if (mechrc == MECH_OK) {
418
+ send_auth(mechlist_data, nmechlist_data);
419
+ state = SREQ_S_WAIT;
420
+ } else if (mechrc == MECH_UNAVAILABLE) {
450
421
  state = SREQ_S_ERROR;
451
422
  } else {
452
423
  state = SREQ_S_HELLODONE;
@@ -456,17 +427,17 @@ handle_read(lcbio_CTX *ioctx, unsigned)
456
427
 
457
428
  case PROTOCOL_BINARY_CMD_SASL_AUTH: {
458
429
  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
459
- sreq->send_hello();
430
+ send_hello();
460
431
  state = SREQ_S_AUTHDONE;
461
432
  break;
462
433
  }
463
434
 
464
435
  if (status != PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
465
- sreq->set_error(LCB_AUTH_ERROR, "SASL AUTH failed");
436
+ set_error(LCB_AUTH_ERROR, "SASL AUTH failed");
466
437
  state = SREQ_S_ERROR;
467
438
  break;
468
439
  }
469
- if (sreq->send_step(resp) && sreq->send_hello()) {
440
+ if (send_step(resp) && send_hello()) {
470
441
  state = SREQ_S_WAIT;
471
442
  } else {
472
443
  state = SREQ_S_ERROR;
@@ -476,8 +447,8 @@ handle_read(lcbio_CTX *ioctx, unsigned)
476
447
 
477
448
  case PROTOCOL_BINARY_CMD_SASL_STEP: {
478
449
  if (status != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
479
- lcb_log(LOGARGS(sreq, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(sreq), status);
480
- sreq->set_error(LCB_AUTH_ERROR, "SASL Step Failed");
450
+ lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(this), status);
451
+ set_error(LCB_AUTH_ERROR, "SASL Step Failed");
481
452
  state = SREQ_S_ERROR;
482
453
  } else {
483
454
  /* Wait for pipelined HELLO response */
@@ -489,15 +460,15 @@ handle_read(lcbio_CTX *ioctx, unsigned)
489
460
  case PROTOCOL_BINARY_CMD_HELLO: {
490
461
  state = SREQ_S_HELLODONE;
491
462
  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
492
- if (!sreq->read_hello(resp)) {
493
- sreq->set_error(LCB_PROTOCOL_ERROR, "Couldn't parse HELLO");
463
+ if (!read_hello(resp)) {
464
+ set_error(LCB_PROTOCOL_ERROR, "Couldn't parse HELLO");
494
465
  }
495
466
  } else if (status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ||
496
467
  status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED) {
497
- lcb_log(LOGARGS(sreq, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(sreq));
468
+ lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(this));
498
469
  /* nothing */
499
470
  } else {
500
- sreq->set_error(LCB_PROTOCOL_ERROR, "Hello response unexpected");
471
+ set_error(LCB_PROTOCOL_ERROR, "Hello response unexpected");
501
472
  state = SREQ_S_ERROR;
502
473
  }
503
474
  break;
@@ -505,8 +476,8 @@ handle_read(lcbio_CTX *ioctx, unsigned)
505
476
 
506
477
  default: {
507
478
  state = SREQ_S_ERROR;
508
- lcb_log(LOGARGS(sreq, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(sreq), resp.opcode(), resp.status());
509
- sreq->set_error(LCB_NOT_SUPPORTED, "Received unknown response");
479
+ lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(this), resp.opcode(), resp.status());
480
+ set_error(LCB_NOT_SUPPORTED, "Received unknown response");
510
481
  break;
511
482
  }
512
483
  }
@@ -517,12 +488,12 @@ handle_read(lcbio_CTX *ioctx, unsigned)
517
488
 
518
489
  // Once there is no more any dependencies on the buffers, we can succeed
519
490
  // or fail the request, potentially destroying the underlying connection
520
- if (sreq->has_error()) {
521
- sreq->fail();
491
+ if (has_error()) {
492
+ fail();
522
493
  } else if (state == SREQ_S_ERROR) {
523
- sreq->fail(LCB_ERROR, "FIXME: Error code set without description");
494
+ fail(LCB_ERROR, "FIXME: Error code set without description");
524
495
  } else if (state == SREQ_S_HELLODONE) {
525
- sreq->success();
496
+ success();
526
497
  } else {
527
498
  goto GT_NEXT_PACKET;
528
499
  }
@@ -531,17 +502,17 @@ handle_read(lcbio_CTX *ioctx, unsigned)
531
502
  static void
532
503
  handle_ioerr(lcbio_CTX *ctx, lcb_error_t err)
533
504
  {
534
- mc_pSESSREQ sreq = mc_SESSREQ::get(lcbio_ctx_data(ctx));
505
+ SessionRequestImpl* sreq = SessionRequestImpl::get(lcbio_ctx_data(ctx));
535
506
  sreq->fail(err, "IO Error");
536
507
  }
537
508
 
538
- static void cleanup_negotiated(mc_pSESSINFO ctx) {
509
+ static void cleanup_negotiated(SessionInfo* ctx) {
539
510
  delete ctx;
540
511
  }
541
512
 
542
513
  void
543
- mc_SESSREQ::start(lcbio_SOCKET *sock, lcb_settings *settings) {
544
- sasl = new mc_SESSINFO(settings);
514
+ SessionRequestImpl::start(lcbio_SOCKET *sock) {
515
+ info = new SessionInfo();
545
516
 
546
517
  lcb_error_t err = lcbio_sslify_if_needed(sock, settings);
547
518
  if (err != LCB_SUCCESS) {
@@ -551,16 +522,16 @@ mc_SESSREQ::start(lcbio_SOCKET *sock, lcb_settings *settings) {
551
522
  }
552
523
 
553
524
  lcbio_CTXPROCS procs;
554
- procs.cb_err = handle_ioerr;
555
- procs.cb_read = handle_read;
525
+ procs.cb_err = ::handle_ioerr;
526
+ procs.cb_read = ::handle_read;
556
527
  ctx = lcbio_ctx_new(sock, this, &procs);
557
528
  ctx->subsys = "sasl";
558
529
 
559
530
  const lcb_host_t *curhost = lcbio_get_host(sock);
560
- struct lcbio_NAMEINFO nistrs;
531
+ lcbio_NAMEINFO nistrs;
561
532
  lcbio_get_nameinfo(sock, &nistrs);
562
533
 
563
- if (!sasl->setup(nistrs, *curhost, *settings->auth)) {
534
+ if (!setup(nistrs, *curhost, *settings->auth)) {
564
535
  set_error(LCB_EINTERNAL, "Couldn't start SASL client");
565
536
  lcbio_async_signal(timer);
566
537
  return;
@@ -571,11 +542,10 @@ mc_SESSREQ::start(lcbio_SOCKET *sock, lcb_settings *settings) {
571
542
  LCBIO_CTX_RSCHEDULE(ctx, 24);
572
543
  }
573
544
 
574
-
575
- mc_SESSREQ::~mc_SESSREQ()
545
+ SessionRequestImpl::~SessionRequestImpl()
576
546
  {
577
- if (sasl) {
578
- delete sasl;
547
+ if (info) {
548
+ delete info;
579
549
  }
580
550
  if (timer) {
581
551
  lcbio_timer_destroy(timer);
@@ -583,35 +553,31 @@ mc_SESSREQ::~mc_SESSREQ()
583
553
  if (ctx) {
584
554
  lcbio_ctx_close(ctx, NULL, NULL);
585
555
  }
556
+ if (sasl_client) {
557
+ cbsasl_dispose(&sasl_client);
558
+ }
586
559
  }
587
560
 
588
- void mc_sessreq_cancel(mc_pSESSREQ sreq) {
561
+ void lcb::sessreq_cancel(SessionRequest *sreq) {
589
562
  sreq->cancel();
590
563
  }
591
564
 
592
- mc_pSESSREQ
593
- mc_sessreq_start(lcbio_SOCKET *sock, lcb_settings *settings,
565
+ SessionRequest *
566
+ SessionRequest::start(lcbio_SOCKET *sock, lcb_settings_st *settings,
594
567
  uint32_t tmo, lcbio_CONNDONE_cb callback, void *data)
595
568
  {
596
- mc_pSESSREQ sreq = new mc_SESSREQ(callback, data, tmo, sock->io);
597
- sreq->start(sock, settings);
569
+ SessionRequestImpl* sreq = new SessionRequestImpl(callback, data, tmo, sock->io, settings);
570
+ sreq->start(sock);
598
571
  return sreq;
599
572
  }
600
573
 
601
- mc_pSESSINFO mc_sess_get(lcbio_SOCKET *sock) {
602
- return static_cast<mc_pSESSINFO>(
603
- lcbio_protoctx_get(sock, LCBIO_PROTOCTX_SESSINFO));
604
- }
605
-
606
- const char *mc_sess_get_saslmech(mc_pSESSINFO info) {
607
- return info->mech.c_str();
574
+ SessionInfo*
575
+ SessionInfo::get(lcbio_SOCKET *sock) {
576
+ return static_cast<SessionInfo*>(lcbio_protoctx_get(sock, LCBIO_PROTOCTX_SESSINFO));
608
577
  }
609
578
 
610
- int mc_sess_chkfeature(mc_pSESSINFO info, uint16_t feature) {
611
- for (size_t ii = 0; ii < info->server_features.size(); ++ii) {
612
- if (info->server_features[ii] == feature) {
613
- return 1;
614
- }
615
- }
616
- return 0;
579
+ bool
580
+ SessionInfo::has_feature(uint16_t feature) const {
581
+ return std::find(server_features.begin(), server_features.end(), feature)
582
+ != server_features.end();
617
583
  }