libcouchbase 0.3.3 → 1.0.0

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