libcouchbase 0.3.3 → 1.0.0

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/CMakeLists.txt +6 -8
  3. data/ext/libcouchbase/README.markdown +2 -2
  4. data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
  5. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
  7. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
  10. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  11. data/ext/libcouchbase/cmake/source_files.cmake +21 -5
  12. data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
  13. data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
  14. data/ext/libcouchbase/example/users/README +48 -0
  15. data/ext/libcouchbase/example/users/users.c +147 -0
  16. data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
  17. data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
  18. data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
  19. data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
  20. data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
  21. data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
  22. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
  23. data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
  24. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  25. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  26. data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
  27. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  28. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  29. data/ext/libcouchbase/src/README.md +0 -2
  30. data/ext/libcouchbase/src/auth-priv.h +23 -4
  31. data/ext/libcouchbase/src/auth.cc +51 -43
  32. data/ext/libcouchbase/src/bootstrap.cc +244 -0
  33. data/ext/libcouchbase/src/bootstrap.h +58 -38
  34. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
  35. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  36. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  38. data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
  39. data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
  40. data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
  41. data/ext/libcouchbase/src/cbft.cc +22 -27
  42. data/ext/libcouchbase/src/cntl.cc +56 -22
  43. data/ext/libcouchbase/src/connspec.cc +47 -6
  44. data/ext/libcouchbase/src/connspec.h +27 -0
  45. data/ext/libcouchbase/src/dns-srv.cc +147 -0
  46. data/ext/libcouchbase/src/dump.cc +3 -3
  47. data/ext/libcouchbase/src/errmap.cc +173 -0
  48. data/ext/libcouchbase/src/errmap.h +198 -0
  49. data/ext/libcouchbase/src/getconfig.cc +7 -33
  50. data/ext/libcouchbase/src/handler.cc +118 -7
  51. data/ext/libcouchbase/src/hostlist.cc +0 -36
  52. data/ext/libcouchbase/src/hostlist.h +44 -62
  53. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  54. data/ext/libcouchbase/src/http/http.cc +27 -35
  55. data/ext/libcouchbase/src/http/http.h +1 -34
  56. data/ext/libcouchbase/src/http/http_io.cc +28 -36
  57. data/ext/libcouchbase/src/instance.cc +131 -34
  58. data/ext/libcouchbase/src/internal.h +58 -26
  59. data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
  60. data/ext/libcouchbase/src/jsparse/parser.h +84 -98
  61. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  62. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  63. data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
  64. data/ext/libcouchbase/src/lcbio/connect.h +16 -7
  65. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  66. data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
  67. data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
  68. data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
  69. data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
  70. data/ext/libcouchbase/src/lcbio/manager.h +133 -96
  71. data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
  72. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  73. data/ext/libcouchbase/src/mc/mcreq.c +11 -2
  74. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  75. data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
  76. data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
  77. data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
  78. data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
  79. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  80. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  81. data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
  82. data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
  83. data/ext/libcouchbase/src/newconfig.cc +6 -6
  84. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  85. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  86. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  87. data/ext/libcouchbase/src/operations/durability.cc +6 -26
  88. data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
  89. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  90. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
  91. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  92. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  93. data/ext/libcouchbase/src/operations/stats.cc +3 -8
  94. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  95. data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
  96. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  97. data/ext/libcouchbase/src/packetutils.h +30 -2
  98. data/ext/libcouchbase/src/probes.d +1 -1
  99. data/ext/libcouchbase/src/rdb/rope.c +1 -1
  100. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
  101. data/ext/libcouchbase/src/retryq.cc +52 -14
  102. data/ext/libcouchbase/src/retryq.h +3 -3
  103. data/ext/libcouchbase/src/settings.c +5 -0
  104. data/ext/libcouchbase/src/settings.h +11 -0
  105. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  106. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  107. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  108. data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
  109. data/ext/libcouchbase/src/trace.h +4 -4
  110. data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
  111. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  112. data/ext/libcouchbase/src/views/docreq.h +24 -30
  113. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  114. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  115. data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
  116. data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
  117. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  118. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
  119. data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
  120. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
  121. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  122. data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
  123. data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
  124. data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
  125. data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
  126. data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
  127. data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
  128. data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
  129. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
  130. data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
  131. data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
  132. data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
  133. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
  134. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
  135. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  136. data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
  137. data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
  138. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  139. data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
  140. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  141. data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
  142. data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
  143. data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
  144. data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
  145. data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
  146. data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
  147. data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
  148. data/ext/libcouchbase/tools/cbc.cc +143 -10
  149. data/ext/libcouchbase/tools/docgen/loc.h +1 -1
  150. data/lib/libcouchbase/connection.rb +4 -3
  151. data/lib/libcouchbase/version.rb +1 -1
  152. metadata +37 -28
  153. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  154. data/ext/libcouchbase/src/bootstrap.c +0 -269
  155. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  156. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  157. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  158. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  159. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  160. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  161. data/ext/libcouchbase/src/lcbio/manager.c +0 -584
  162. data/ext/libcouchbase/src/packetutils.c +0 -37
  163. data/ext/libcouchbase/src/simplestring.c +0 -211
  164. data/ext/libcouchbase/src/simplestring.h +0 -228
  165. data/ext/libcouchbase/src/ssobuf.h +0 -82
  166. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  167. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -24,9 +24,6 @@
24
24
  #include <netbuf/netbuf.h>
25
25
 
26
26
  #ifdef __cplusplus
27
- struct lcb_settings_st;
28
- struct lcb_server_st;
29
-
30
27
  namespace lcb {
31
28
 
32
29
  class RetryQueue;
@@ -109,6 +106,10 @@ public:
109
106
  return mutation_tokens;
110
107
  }
111
108
 
109
+ bool supports_compression() const {
110
+ return compsupport;
111
+ }
112
+
112
113
  bool is_connected() const {
113
114
  return connctx != NULL;
114
115
  }
@@ -172,10 +173,13 @@ public:
172
173
 
173
174
  enum ReadState {
174
175
  PKT_READ_COMPLETE,
175
- PKT_READ_PARTIAL
176
+ PKT_READ_PARTIAL,
177
+ PKT_READ_ABORT
176
178
  };
177
179
 
178
180
  ReadState try_read(lcbio_CTX *ctx, rdb_IOROPE *ior);
181
+ int handle_unknown_error(const mc_PACKET *request,
182
+ const MemcachedResponse& resinfo, lcb_error_t& newerr);
179
183
  bool handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt);
180
184
  bool maybe_retry_packet(mc_PACKET *pkt, lcb_error_t err);
181
185
  bool maybe_reconnect_on_fake_timeout(lcb_error_t received_error);
@@ -200,19 +204,11 @@ public:
200
204
  short mutation_tokens;
201
205
 
202
206
  lcbio_CTX *connctx;
203
- lcbio_CONNREQ connreq;
207
+ lcb::io::ConnectionRequest *connreq;
204
208
 
205
209
  /** Request for current connection */
206
210
  lcb_host_t *curhost;
207
211
  };
208
212
  }
209
-
210
- typedef lcb::Server mc_SERVER;
211
- extern "C" {int mcserver_supports_compression(mc_SERVER*);}
212
-
213
- #else
214
- /* C only */
215
- typedef struct mc_SERVER mc_SERVER;
216
- int mcserver_supports_compression(mc_SERVER *server);
217
213
  #endif /* __cplusplus */
218
214
  #endif /* LCB_MCSERVER_H */
@@ -16,6 +16,10 @@
16
16
  */
17
17
 
18
18
  #include <algorithm>
19
+ #include <string>
20
+ #include <sstream>
21
+ #include <vector>
22
+
19
23
  #include "packetutils.h"
20
24
  #include "mcserver.h"
21
25
  #include "logging.h"
@@ -26,6 +30,7 @@
26
30
  #include <cbsasl/cbsasl.h>
27
31
  #include "negotiate.h"
28
32
  #include "ctx-log-inl.h"
33
+ #include "auth-priv.h"
29
34
 
30
35
  using namespace lcb;
31
36
 
@@ -34,6 +39,7 @@ static void cleanup_negotiated(SessionInfo* info);
34
39
  static void handle_ioerr(lcbio_CTX *ctx, lcb_error_t err);
35
40
  #define SESSREQ_LOGFMT "<%s:%s> (SASLREQ=%p) "
36
41
 
42
+
37
43
  static void timeout_handler(void *arg);
38
44
 
39
45
  #define SESSREQ_LOGID(s) get_ctx_host(s->ctx), get_ctx_port(s->ctx), (void*)s
@@ -60,14 +66,18 @@ public:
60
66
  bool setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
61
67
  const lcb::Authenticator& auth);
62
68
  void start(lcbio_SOCKET *sock);
69
+ void send_list_mechs();
63
70
  bool send_hello();
64
71
  bool send_step(const lcb::MemcachedResponse& packet);
65
72
  bool read_hello(const lcb::MemcachedResponse& packet);
66
73
  void send_auth(const char *sasl_data, unsigned ndata);
67
74
  void handle_read(lcbio_CTX *ioctx);
75
+ bool maybe_select_bucket();
68
76
 
69
77
  enum MechStatus { MECH_UNAVAILABLE, MECH_NOT_NEEDED, MECH_OK };
70
78
  MechStatus set_chosen_mech(std::string& mechlist, const char **data, unsigned int *ndata);
79
+ bool request_errmap();
80
+ bool update_errmap(const lcb::MemcachedResponse& packet);
71
81
 
72
82
  SessionRequestImpl(lcbio_CONNDONE_cb callback, void *data, uint32_t timeout, lcbio_TABLE *iot, lcb_settings* settings_)
73
83
  : ctx(NULL), cb(callback), cbdata(data),
@@ -118,8 +128,29 @@ public:
118
128
  delete this;
119
129
  }
120
130
 
121
- void set_error(lcb_error_t error, const char *msg = "") {
122
- lcb_log(LOGARGS(this, ERR), SESSREQ_LOGFMT "Error: 0x%x, %s", SESSREQ_LOGID(this), error, msg);
131
+ void set_error(lcb_error_t error, const char *msg, const lcb::MemcachedResponse *packet = NULL) {
132
+ char *err_ref = NULL, *err_ctx = NULL;
133
+ if (packet) {
134
+ MemcachedResponse::parse_enhanced_error(packet->value(), packet->vallen(), &err_ref, &err_ctx);
135
+ }
136
+ if (err_ref || err_ctx) {
137
+ std::stringstream emsg;
138
+ if (err_ref) {
139
+ emsg << "ref: \"" << err_ref << "\"";
140
+ }
141
+ if (err_ctx) {
142
+ if (err_ref) {
143
+ emsg << ", ";
144
+ }
145
+ emsg << "context: \"" << err_ctx << "\"";
146
+ }
147
+ lcb_log(LOGARGS(this, ERR), SESSREQ_LOGFMT "Error: 0x%x, %s (%s)",
148
+ SESSREQ_LOGID(this), error, msg, emsg.str().c_str());
149
+ free(err_ref);
150
+ free(err_ctx);
151
+ } else {
152
+ lcb_log(LOGARGS(this, ERR), SESSREQ_LOGFMT "Error: 0x%x, %s", SESSREQ_LOGID(this), error, msg);
153
+ }
123
154
  if (last_err == LCB_SUCCESS) {
124
155
  last_err = error;
125
156
  }
@@ -133,6 +164,7 @@ public:
133
164
  cbsasl_secret_t secret;
134
165
  char buffer[256];
135
166
  } u_auth;
167
+ std::string username;
136
168
 
137
169
  lcbio_CTX *ctx;
138
170
  lcbio_CONNDONE_cb cb;
@@ -152,16 +184,12 @@ static int
152
184
  sasl_get_username(void *context, int id, const char **result, unsigned int *len)
153
185
  {
154
186
  SessionRequestImpl *ctx = SessionRequestImpl::get(context);
155
- const char *u = NULL, *p = NULL;
156
187
  if (!context || !result || (id != CBSASL_CB_USER && id != CBSASL_CB_AUTHNAME)) {
157
188
  return SASL_BADPARAM;
158
189
  }
159
190
 
160
- lcbauth_get_upass(ctx->settings->auth, &u, &p);
161
- *result = u;
162
- if (len) {
163
- *len = (unsigned int)strlen(*result);
164
- }
191
+ *result = ctx->username.c_str();
192
+ *len = ctx->username.size();
165
193
 
166
194
  return SASL_OK;
167
195
  }
@@ -207,22 +235,21 @@ SessionRequestImpl::setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
207
235
  sasl_callbacks[ii].context = this;
208
236
  }
209
237
 
210
- const char *pass = NULL, *user = NULL;
211
- lcbauth_get_upass(&auth, &user, &pass);
238
+ // Get the credentials
239
+ username = auth.username_for(settings->bucket);
240
+ const std::string& pass = auth.password_for(settings->bucket);
212
241
 
213
- if (pass) {
214
- unsigned long pwlen = (unsigned long)strlen(pass);
242
+ if (!pass.empty()) {
215
243
  size_t maxlen = sizeof(u_auth.buffer) - offsetof(cbsasl_secret_t, data);
216
- u_auth.secret.len = pwlen;
244
+ u_auth.secret.len = pass.size();
217
245
 
218
- if (pwlen < maxlen) {
219
- memcpy(u_auth.secret.data, pass, pwlen);
246
+ if (pass.size() < maxlen) {
247
+ memcpy(u_auth.secret.data, pass.c_str(), pass.size());
220
248
  } else {
221
249
  return false;
222
250
  }
223
251
  }
224
252
 
225
-
226
253
  cbsasl_error_t saslerr = cbsasl_client_new(
227
254
  "couchbase", host.host, nistrs.local, nistrs.remote,
228
255
  sasl_callbacks, 0, &sasl_client);
@@ -323,6 +350,11 @@ SessionRequestImpl::send_hello()
323
350
 
324
351
  unsigned nfeatures = 0;
325
352
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TLS;
353
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_XATTR;
354
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_SELECT_BUCKET;
355
+ if (settings->use_errmap) {
356
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_XERROR;
357
+ }
326
358
  if (settings->tcp_nodelay) {
327
359
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TCPNODELAY;
328
360
  }
@@ -359,10 +391,19 @@ SessionRequestImpl::send_hello()
359
391
  lcb_U16 tmp = htons(features[ii]);
360
392
  lcbio_ctx_put(ctx, &tmp, sizeof tmp);
361
393
  }
394
+
362
395
  lcbio_ctx_rwant(ctx, 24);
363
396
  return true;
364
397
  }
365
398
 
399
+ void
400
+ SessionRequestImpl::send_list_mechs()
401
+ {
402
+ lcb::MemcachedRequest req(PROTOCOL_BINARY_CMD_SASL_LIST_MECHS);
403
+ lcbio_ctx_put(ctx, req.data(), req.size());
404
+ LCBIO_CTX_RSCHEDULE(ctx, 24);
405
+ }
406
+
366
407
  bool
367
408
  SessionRequestImpl::read_hello(const lcb::MemcachedResponse& resp)
368
409
  {
@@ -374,18 +415,74 @@ SessionRequestImpl::read_hello(const lcb::MemcachedResponse& resp)
374
415
  lcb_U16 tmp;
375
416
  memcpy(&tmp, cur, sizeof(tmp));
376
417
  tmp = ntohs(tmp);
377
- lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Found feature 0x%x (%s)", SESSREQ_LOGID(this), tmp, protocol_feature_2_text(tmp));
418
+ lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server supports feature: 0x%x (%s)", SESSREQ_LOGID(this), tmp, protocol_feature_2_text(tmp));
378
419
  info->server_features.push_back(tmp);
379
420
  }
380
421
  return true;
381
422
  }
382
423
 
383
- typedef enum {
384
- SREQ_S_WAIT,
385
- SREQ_S_AUTHDONE,
386
- SREQ_S_HELLODONE,
387
- SREQ_S_ERROR
388
- } sreq_STATE;
424
+ bool
425
+ SessionRequestImpl::request_errmap() {
426
+ lcb::MemcachedRequest hdr(PROTOCOL_BINARY_CMD_GET_ERROR_MAP);
427
+ uint16_t version = htons(1);
428
+ hdr.sizes(0, 0, 2);
429
+ const char *p = reinterpret_cast<const char *>(&version);
430
+
431
+ lcbio_ctx_put(ctx, hdr.data(), hdr.size());
432
+ lcbio_ctx_put(ctx, p, 2);
433
+ lcbio_ctx_rwant(ctx, 24);
434
+ return true;
435
+ }
436
+
437
+ bool
438
+ SessionRequestImpl::update_errmap(const lcb::MemcachedResponse& resp)
439
+ {
440
+ // Get the error map object
441
+ using lcb::errmap::ErrorMap;
442
+
443
+ std::string errmsg;
444
+ ErrorMap& mm = *settings->errmap;
445
+ ErrorMap::ParseStatus status = mm.parse(
446
+ resp.body<const char*>(), resp.bodylen(), errmsg);
447
+
448
+ if (status != ErrorMap::UPDATED && status != ErrorMap::NOT_UPDATED) {
449
+ errmsg = "Couldn't update error map: " + errmsg;
450
+ set_error(LCB_PROTOCOL_ERROR, errmsg.c_str());
451
+ return false;
452
+ }
453
+
454
+ return true;
455
+ }
456
+
457
+ // Returns true if sending the SELECT_BUCKET command, false otherwise.
458
+ bool
459
+ SessionRequestImpl::maybe_select_bucket() {
460
+
461
+ // Only send a SELECT_BUCKET if we have the SELECT_BUCKET bit enabled.
462
+ if (!info->has_feature(PROTOCOL_BINARY_FEATURE_SELECT_BUCKET)) {
463
+ return false;
464
+ }
465
+
466
+ if (!settings->select_bucket) {
467
+ lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SELECT_BUCKET Disabled by application", SESSREQ_LOGID(this));
468
+ return false;
469
+ }
470
+
471
+ // send the SELECT_BUCKET command:
472
+ lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "Sending SELECT_BUCKET", SESSREQ_LOGID(this));
473
+ lcb::MemcachedRequest req(PROTOCOL_BINARY_CMD_SELECT_BUCKET);
474
+ req.sizes(0, strlen(settings->bucket), 0);
475
+ lcbio_ctx_put(ctx, req.data(), req.size());
476
+ lcbio_ctx_put(ctx, settings->bucket, strlen(settings->bucket));
477
+ LCBIO_CTX_RSCHEDULE(ctx, 24);
478
+ return true;
479
+ }
480
+
481
+ static bool isUnsupported(uint16_t status) {
482
+ return status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED ||
483
+ status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ||
484
+ status == PROTOCOL_BINARY_RESPONSE_EACCESS;
485
+ }
389
486
 
390
487
  /**
391
488
  * It's assumed the server buffers will be reset upon close(), so we must make
@@ -396,7 +493,7 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
396
493
  {
397
494
  lcb::MemcachedResponse resp;
398
495
  unsigned required;
399
- sreq_STATE state = SREQ_S_WAIT;
496
+ bool completed = false;
400
497
 
401
498
  GT_NEXT_PACKET:
402
499
 
@@ -415,68 +512,92 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
415
512
  MechStatus mechrc = set_chosen_mech(mechs, &mechlist_data, &nmechlist_data);
416
513
  if (mechrc == MECH_OK) {
417
514
  send_auth(mechlist_data, nmechlist_data);
418
- state = SREQ_S_WAIT;
419
515
  } else if (mechrc == MECH_UNAVAILABLE) {
420
- state = SREQ_S_ERROR;
516
+ // Do nothing - error already set
421
517
  } else {
422
- state = SREQ_S_HELLODONE;
518
+ completed = !maybe_select_bucket();
423
519
  }
424
520
  break;
425
521
  }
426
522
 
427
523
  case PROTOCOL_BINARY_CMD_SASL_AUTH: {
428
524
  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
429
- send_hello();
430
- state = SREQ_S_AUTHDONE;
431
- break;
432
- }
433
-
434
- if (status != PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
435
- set_error(LCB_AUTH_ERROR, "SASL AUTH failed");
436
- state = SREQ_S_ERROR;
525
+ completed = !maybe_select_bucket();
437
526
  break;
438
- }
439
- if (send_step(resp) && send_hello()) {
440
- state = SREQ_S_WAIT;
527
+ } else if (status == PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
528
+ send_step(resp);
441
529
  } else {
442
- state = SREQ_S_ERROR;
530
+ set_error(LCB_AUTH_ERROR, "SASL AUTH failed", &resp);
531
+ break;
443
532
  }
444
533
  break;
445
534
  }
446
535
 
447
536
  case PROTOCOL_BINARY_CMD_SASL_STEP: {
448
- if (status != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
449
- lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(this), status);
450
- set_error(LCB_AUTH_ERROR, "SASL Step Failed");
451
- state = SREQ_S_ERROR;
537
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
538
+ completed = !maybe_select_bucket();
452
539
  } else {
453
- /* Wait for pipelined HELLO response */
454
- state = SREQ_S_AUTHDONE;
540
+ lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(this), status);
541
+ set_error(LCB_AUTH_ERROR, "SASL Step failed", &resp);
455
542
  }
456
543
  break;
457
544
  }
458
545
 
459
546
  case PROTOCOL_BINARY_CMD_HELLO: {
460
- state = SREQ_S_HELLODONE;
461
547
  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
462
548
  if (!read_hello(resp)) {
463
549
  set_error(LCB_PROTOCOL_ERROR, "Couldn't parse HELLO");
550
+ break;
464
551
  }
465
- } else if (status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ||
466
- status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED) {
552
+ } else if (isUnsupported(status)) {
467
553
  lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(this));
468
- /* nothing */
469
554
  } else {
470
- set_error(LCB_PROTOCOL_ERROR, "Hello response unexpected");
471
- state = SREQ_S_ERROR;
555
+ lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for HELLO", SESSREQ_LOGID(this), status);
556
+ set_error(LCB_PROTOCOL_ERROR, "Hello response unexpected", &resp);
557
+ break;
558
+ }
559
+
560
+ if (info->has_feature(PROTOCOL_BINARY_FEATURE_XERROR)) {
561
+ request_errmap();
562
+ } else {
563
+ lcb_log(LOGARGS(this, TRACE), SESSREQ_LOGFMT "GET_ERRORMAP unsupported/disabled", SESSREQ_LOGID(this));
564
+ }
565
+
566
+ // In any event, it's also time to send the LIST_MECHS request
567
+ send_list_mechs();
568
+ break;
569
+ }
570
+
571
+ case PROTOCOL_BINARY_CMD_GET_ERROR_MAP: {
572
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
573
+ if (!update_errmap(resp)) {
574
+ }
575
+ } else if (isUnsupported(status)) {
576
+ lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server does not support GET_ERRMAP (0x%x)", SESSREQ_LOGID(this), status);
577
+ } else {
578
+ lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for GET_ERRMAP", SESSREQ_LOGID(this), status);
579
+ set_error(LCB_PROTOCOL_ERROR, "GET_ERRMAP response unexpected", &resp);
580
+ }
581
+ // Note, there is no explicit state transition here. LIST_MECHS is
582
+ // pipelined after this request.
583
+ break;
584
+ }
585
+
586
+ case PROTOCOL_BINARY_CMD_SELECT_BUCKET: {
587
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
588
+ completed = true;
589
+ } else if (status == PROTOCOL_BINARY_RESPONSE_EACCESS) {
590
+ set_error(LCB_AUTH_ERROR, "Provided credentials not allowed for bucket", &resp);
591
+ } else {
592
+ lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for SELECT_BUCKET", SESSREQ_LOGID(this), status);
593
+ set_error(LCB_PROTOCOL_ERROR, "Other auth error", &resp);
472
594
  }
473
595
  break;
474
596
  }
475
597
 
476
598
  default: {
477
- state = SREQ_S_ERROR;
478
599
  lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(this), resp.opcode(), resp.status());
479
- set_error(LCB_NOT_SUPPORTED, "Received unknown response");
600
+ set_error(LCB_NOT_SUPPORTED, "Received unknown response", &resp);
480
601
  break;
481
602
  }
482
603
  }
@@ -489,9 +610,7 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
489
610
  // or fail the request, potentially destroying the underlying connection
490
611
  if (has_error()) {
491
612
  fail();
492
- } else if (state == SREQ_S_ERROR) {
493
- fail(LCB_ERROR, "FIXME: Error code set without description");
494
- } else if (state == SREQ_S_HELLODONE) {
613
+ } else if (completed) {
495
614
  success();
496
615
  } else {
497
616
  goto GT_NEXT_PACKET;
@@ -536,8 +655,12 @@ SessionRequestImpl::start(lcbio_SOCKET *sock) {
536
655
  return;
537
656
  }
538
657
 
539
- lcb::MemcachedRequest hdr(PROTOCOL_BINARY_CMD_SASL_LIST_MECHS);
540
- lcbio_ctx_put(ctx, hdr.data(), hdr.size());
658
+ if (settings->send_hello) {
659
+ send_hello();
660
+ } else {
661
+ lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "HELLO negotiation disabled by user", SESSREQ_LOGID(this));
662
+ send_list_mechs();
663
+ }
541
664
  LCBIO_CTX_RSCHEDULE(ctx, 24);
542
665
  }
543
666
 
@@ -557,10 +680,6 @@ SessionRequestImpl::~SessionRequestImpl()
557
680
  }
558
681
  }
559
682
 
560
- void lcb::sessreq_cancel(SessionRequest *sreq) {
561
- sreq->cancel();
562
- }
563
-
564
683
  SessionRequest *
565
684
  SessionRequest::start(lcbio_SOCKET *sock, lcb_settings_st *settings,
566
685
  uint32_t tmo, lcbio_CONNDONE_cb callback, void *data)