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.
- checksums.yaml +4 -4
- data/ext/libcouchbase/CMakeLists.txt +6 -8
- data/ext/libcouchbase/README.markdown +2 -2
- data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
- data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
- data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
- data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
- data/ext/libcouchbase/cmake/defs.mk.in +0 -2
- data/ext/libcouchbase/cmake/source_files.cmake +21 -5
- data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
- data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
- data/ext/libcouchbase/example/users/README +48 -0
- data/ext/libcouchbase/example/users/users.c +147 -0
- data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
- data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
- data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
- data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
- data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
- data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
- data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
- data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
- data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
- data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
- data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
- data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
- data/ext/libcouchbase/src/README.md +0 -2
- data/ext/libcouchbase/src/auth-priv.h +23 -4
- data/ext/libcouchbase/src/auth.cc +51 -43
- data/ext/libcouchbase/src/bootstrap.cc +244 -0
- data/ext/libcouchbase/src/bootstrap.h +58 -38
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
- data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
- data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
- data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
- data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
- data/ext/libcouchbase/src/cbft.cc +22 -27
- data/ext/libcouchbase/src/cntl.cc +56 -22
- data/ext/libcouchbase/src/connspec.cc +47 -6
- data/ext/libcouchbase/src/connspec.h +27 -0
- data/ext/libcouchbase/src/dns-srv.cc +147 -0
- data/ext/libcouchbase/src/dump.cc +3 -3
- data/ext/libcouchbase/src/errmap.cc +173 -0
- data/ext/libcouchbase/src/errmap.h +198 -0
- data/ext/libcouchbase/src/getconfig.cc +7 -33
- data/ext/libcouchbase/src/handler.cc +118 -7
- data/ext/libcouchbase/src/hostlist.cc +0 -36
- data/ext/libcouchbase/src/hostlist.h +44 -62
- data/ext/libcouchbase/src/http/http-priv.h +125 -112
- data/ext/libcouchbase/src/http/http.cc +27 -35
- data/ext/libcouchbase/src/http/http.h +1 -34
- data/ext/libcouchbase/src/http/http_io.cc +28 -36
- data/ext/libcouchbase/src/instance.cc +131 -34
- data/ext/libcouchbase/src/internal.h +58 -26
- data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
- data/ext/libcouchbase/src/jsparse/parser.h +84 -98
- data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
- data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
- data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
- data/ext/libcouchbase/src/lcbio/connect.h +16 -7
- data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
- data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
- data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
- data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
- data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
- data/ext/libcouchbase/src/lcbio/manager.h +133 -96
- data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
- data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
- data/ext/libcouchbase/src/mc/mcreq.c +11 -2
- data/ext/libcouchbase/src/mc/mcreq.h +9 -2
- data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
- data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
- data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
- data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
- data/ext/libcouchbase/src/mctx-helper.h +51 -0
- data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
- data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
- data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
- data/ext/libcouchbase/src/newconfig.cc +6 -6
- data/ext/libcouchbase/src/nodeinfo.cc +2 -2
- data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
- data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
- data/ext/libcouchbase/src/operations/durability.cc +6 -26
- data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
- data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
- data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
- data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
- data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
- data/ext/libcouchbase/src/operations/stats.cc +3 -8
- data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
- data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
- data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
- data/ext/libcouchbase/src/packetutils.h +30 -2
- data/ext/libcouchbase/src/probes.d +1 -1
- data/ext/libcouchbase/src/rdb/rope.c +1 -1
- data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
- data/ext/libcouchbase/src/retryq.cc +52 -14
- data/ext/libcouchbase/src/retryq.h +3 -3
- data/ext/libcouchbase/src/settings.c +5 -0
- data/ext/libcouchbase/src/settings.h +11 -0
- data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
- data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
- data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
- data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
- data/ext/libcouchbase/src/trace.h +4 -4
- data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
- data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
- data/ext/libcouchbase/src/views/docreq.h +24 -30
- data/ext/libcouchbase/src/views/viewreq.cc +318 -0
- data/ext/libcouchbase/src/views/viewreq.h +43 -13
- data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
- data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
- data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
- data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
- data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
- data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
- data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
- data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
- data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
- data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
- data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
- data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
- data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
- data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
- data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
- data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
- data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
- data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
- data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
- data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
- data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
- data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
- data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
- data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
- data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
- data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
- data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
- data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
- data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
- data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
- data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
- data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
- data/ext/libcouchbase/tools/cbc.cc +143 -10
- data/ext/libcouchbase/tools/docgen/loc.h +1 -1
- data/lib/libcouchbase/connection.rb +4 -3
- data/lib/libcouchbase/version.rb +1 -1
- metadata +37 -28
- data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
- data/ext/libcouchbase/src/bootstrap.c +0 -269
- data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
- data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
- data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
- data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
- data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
- data/ext/libcouchbase/src/lcbio/connect.c +0 -557
- data/ext/libcouchbase/src/lcbio/manager.c +0 -584
- data/ext/libcouchbase/src/packetutils.c +0 -37
- data/ext/libcouchbase/src/simplestring.c +0 -211
- data/ext/libcouchbase/src/simplestring.h +0 -228
- data/ext/libcouchbase/src/ssobuf.h +0 -82
- data/ext/libcouchbase/src/views/viewreq.c +0 -358
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
161
|
-
*
|
|
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
|
-
|
|
211
|
-
|
|
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 =
|
|
244
|
+
u_auth.secret.len = pass.size();
|
|
217
245
|
|
|
218
|
-
if (
|
|
219
|
-
memcpy(u_auth.secret.data, pass,
|
|
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 "
|
|
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
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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
|
-
|
|
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
|
-
|
|
516
|
+
// Do nothing - error already set
|
|
421
517
|
} else {
|
|
422
|
-
|
|
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
|
-
|
|
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
|
-
|
|
440
|
-
state = SREQ_S_WAIT;
|
|
527
|
+
} else if (status == PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
|
|
528
|
+
send_step(resp);
|
|
441
529
|
} else {
|
|
442
|
-
|
|
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
|
|
449
|
-
|
|
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
|
-
|
|
454
|
-
|
|
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
|
|
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
|
-
|
|
471
|
-
|
|
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 (
|
|
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
|
-
|
|
540
|
-
|
|
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)
|