libcouchbase 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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
  }