libcouchbase 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,86 +0,0 @@
1
- /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
- /*
3
- * Copyright 2012 Couchbase, Inc.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
-
18
- #ifndef LIBCOUCHBASE_HASHSET_H
19
- #define LIBCOUCHBASE_HASHSET_H 1
20
-
21
- #ifdef __cplusplus
22
- extern "C" {
23
- #endif
24
-
25
- struct hashset_st {
26
- lcb_size_t nbits;
27
- lcb_size_t mask;
28
-
29
- lcb_size_t capacity;
30
- lcb_size_t *items;
31
- lcb_size_t nitems;
32
- };
33
-
34
- typedef struct hashset_st *hashset_t;
35
-
36
- /* create hashset instance */
37
- hashset_t hashset_create(void);
38
-
39
- /* destroy hashset instance */
40
- void hashset_destroy(hashset_t set);
41
-
42
- lcb_size_t hashset_num_items(hashset_t set);
43
-
44
- /**
45
- * Makes a list of items inside the hashset.
46
- * @param set the hashset
47
- * @param itemlist an allocated array large enough to hold the number
48
- * of items in the hashset (use hashset_num_items). If this is NULL
49
- * then a list is allocated for you
50
- *
51
- * @return the item list. If the @itemlist param argument was
52
- * not-null, then this is the same list; if it was NULL then this
53
- * is an allocated list which should be released using @itemlist
54
- * free(). It will return NULL if the hashset is empty or memory
55
- * allocation for @itemlist was failed.
56
- */
57
- void **hashset_get_items(hashset_t set, void **itemlist);
58
-
59
-
60
- /* add item into the hashset.
61
- *
62
- * @note 0 and 1 is special values, meaning nil and deleted items. the
63
- * function will return -1 indicating error.
64
- *
65
- * returns zero if the item already in the set and non-zero otherwise
66
- */
67
- int hashset_add(hashset_t set, void *item);
68
-
69
- /* remove item from the hashset
70
- *
71
- * returns non-zero if the item was removed and zero if the item wasn't
72
- * exist
73
- */
74
- int hashset_remove(hashset_t set, void *item);
75
-
76
- /* check if existence of the item
77
- *
78
- * returns non-zero if the item exists and zero otherwise
79
- */
80
- int hashset_is_member(hashset_t set, void *item);
81
-
82
- #ifdef __cplusplus
83
- }
84
- #endif
85
-
86
- #endif
@@ -1,657 +0,0 @@
1
- /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
- /*
3
- * Copyright 2014 Couchbase, Inc.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
-
18
- #include "packetutils.h"
19
- #include "simplestring.h"
20
- #include "mcserver.h"
21
- #include "logging.h"
22
- #include "settings.h"
23
- #include <lcbio/lcbio.h>
24
- #include <lcbio/timer-ng.h>
25
- #include <lcbio/ssl.h>
26
- #include <cbsasl/cbsasl.h>
27
- #include "negotiate.h"
28
- #include "ctx-log-inl.h"
29
-
30
- #define LOGARGS(ctx, lvl) ctx->inner->settings, "negotiation", LCB_LOG_##lvl, __FILE__, __LINE__
31
- static void cleanup_pending(mc_pSESSREQ);
32
- static void cleanup_negotiated(mc_pSESSINFO);
33
- static void bail_pending(mc_pSESSREQ sreq);
34
- #define SESSREQ_LOGFMT "<%s:%s> (SASLREQ=%p) "
35
-
36
- /**
37
- * Inner negotiation structure which is maintained as part of a 'protocol
38
- * context'.
39
- */
40
- struct mc_SESSINFO {
41
- lcbio_PROTOCTX base;
42
- cbsasl_conn_t *sasl;
43
- char *mech;
44
- unsigned int nmech;
45
- lcb_settings *settings;
46
- lcbio_CONNDONE_cb complete;
47
- union {
48
- cbsasl_secret_t secret;
49
- char buffer[256];
50
- } u_auth;
51
- cbsasl_callback_t sasl_callbacks[4];
52
- lcb_U16 features[MEMCACHED_TOTAL_HELLO_FEATURES+1];
53
- };
54
-
55
- /**
56
- * Structure used only for initialization. This is only used for the duration
57
- * of the request for negotiation and is deleted once negotiation has
58
- * completed (or failed).
59
- */
60
- typedef struct mc_SESSREQ {
61
- lcbio_CTX *ctx;
62
- lcbio_CONNDONE_cb cb;
63
- void *data;
64
- lcbio_pTIMER timer;
65
- lcb_error_t err;
66
- mc_pSESSINFO inner;
67
- } neg_PENDING;
68
-
69
- #define SESSREQ_LOGID(s) get_ctx_host(s->ctx), get_ctx_port(s->ctx), (void*)s
70
-
71
- static int
72
- sasl_get_username(void *context, int id, const char **result, unsigned int *len)
73
- {
74
- struct mc_SESSINFO *ctx = context;
75
- const char *u = NULL, *p = NULL;
76
- if (!context || !result || (id != CBSASL_CB_USER && id != CBSASL_CB_AUTHNAME)) {
77
- return SASL_BADPARAM;
78
- }
79
- u = ctx->settings->bucket;
80
- p = lcbauth_get_bpass(ctx->settings->auth, ctx->settings->bucket);
81
- *result = u;
82
- if (len) {
83
- *len = (unsigned int)strlen(*result);
84
- }
85
-
86
- return SASL_OK;
87
- }
88
-
89
- static int
90
- sasl_get_password(cbsasl_conn_t *conn, void *context, int id,
91
- cbsasl_secret_t **psecret)
92
- {
93
- struct mc_SESSINFO *ctx = context;
94
- if (!conn || ! psecret || id != CBSASL_CB_PASS || ctx == NULL) {
95
- return SASL_BADPARAM;
96
- }
97
-
98
- *psecret = &ctx->u_auth.secret;
99
- return SASL_OK;
100
- }
101
-
102
- static lcb_error_t
103
- setup_sasl_params(struct mc_SESSINFO *ctx)
104
- {
105
- int ii;
106
- cbsasl_callback_t *callbacks = ctx->sasl_callbacks;
107
- const char *pass = NULL, *user = NULL;
108
-
109
- callbacks[0].id = CBSASL_CB_USER;
110
- callbacks[0].proc = (int( *)(void)) &sasl_get_username;
111
-
112
- callbacks[1].id = CBSASL_CB_AUTHNAME;
113
- callbacks[1].proc = (int( *)(void)) &sasl_get_username;
114
-
115
- callbacks[2].id = CBSASL_CB_PASS;
116
- callbacks[2].proc = (int( *)(void)) &sasl_get_password;
117
-
118
- callbacks[3].id = CBSASL_CB_LIST_END;
119
- callbacks[3].proc = NULL;
120
- callbacks[3].context = NULL;
121
-
122
- for (ii = 0; ii < 3; ii++) {
123
- callbacks[ii].context = ctx;
124
- }
125
-
126
- memset(&ctx->u_auth, 0, sizeof(ctx->u_auth));
127
- user = ctx->settings->bucket;
128
- pass = lcbauth_get_bpass(ctx->settings->auth, user);
129
-
130
- if (pass) {
131
- unsigned long pwlen;
132
- lcb_size_t maxlen;
133
-
134
- pwlen = (unsigned long)strlen(pass);
135
- maxlen = sizeof(ctx->u_auth.buffer) - offsetof(cbsasl_secret_t, data);
136
- ctx->u_auth.secret.len = pwlen;
137
-
138
- if (pwlen < maxlen) {
139
- memcpy(ctx->u_auth.secret.data, pass, pwlen);
140
- } else {
141
- return LCB_EINVAL;
142
- }
143
- }
144
- return LCB_SUCCESS;
145
- }
146
-
147
- static void
148
- close_cb(lcbio_SOCKET *s, int reusable, void *arg)
149
- {
150
- *(lcbio_SOCKET **)arg = s;
151
- lcbio_ref(s);
152
- lcb_assert(reusable);
153
- }
154
-
155
- static void
156
- negotiation_success(mc_pSESSREQ sreq)
157
- {
158
- /** Dislodge the connection, and return it back to the caller */
159
- lcbio_SOCKET *s;
160
-
161
- lcbio_ctx_close(sreq->ctx, close_cb, &s);
162
- sreq->ctx = NULL;
163
-
164
- lcbio_protoctx_add(s, &sreq->inner->base);
165
- sreq->inner = NULL;
166
-
167
- /** Invoke the callback, marking it a success */
168
- sreq->cb(s, sreq->data, LCB_SUCCESS, 0);
169
- lcbio_unref(s);
170
- cleanup_pending(sreq);
171
- }
172
-
173
- static void
174
- bail_pending(mc_pSESSREQ sreq)
175
- {
176
- sreq->cb(NULL, sreq->data, sreq->err, 0);
177
- cleanup_pending(sreq);
178
- }
179
-
180
- static void
181
- set_error_ex(mc_pSESSREQ sreq, lcb_error_t err, const char *msg)
182
- {
183
- lcb_log(LOGARGS(sreq, ERR), SESSREQ_LOGFMT "Error: 0x%x, %s", SESSREQ_LOGID(sreq), err, msg);
184
- if (sreq->err == LCB_SUCCESS) {
185
- sreq->err = err;
186
- }
187
- }
188
-
189
- static void
190
- timeout_handler(void *arg)
191
- {
192
- mc_pSESSREQ sreq = arg;
193
- set_error_ex(sreq, LCB_ETIMEDOUT, "Negotiation timed out");
194
- bail_pending(sreq);
195
- }
196
-
197
- /**
198
- * Called to retrive the mechlist from the packet.
199
- * @return 0 to continue authentication, 1 if no authentication needed, or
200
- * -1 on error.
201
- */
202
- static int
203
- set_chosen_mech(mc_pSESSREQ sreq, lcb_string *mechlist, const char **data,
204
- unsigned int *ndata)
205
- {
206
- cbsasl_error_t saslerr;
207
- const char *chosenmech;
208
- mc_pSESSINFO ctx = sreq->inner;
209
-
210
- lcb_assert(sreq->inner);
211
- if (ctx->settings->sasl_mech_force) {
212
- char *forcemech = ctx->settings->sasl_mech_force;
213
- if (!strstr(mechlist->base, forcemech)) {
214
- /** Requested mechanism not found */
215
- set_error_ex(sreq, LCB_SASLMECH_UNAVAILABLE, mechlist->base);
216
- return -1;
217
- }
218
-
219
- lcb_string_clear(mechlist);
220
- if (lcb_string_appendz(mechlist, forcemech)) {
221
- set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
222
- return -1;
223
- }
224
- }
225
-
226
- saslerr = cbsasl_client_start(ctx->sasl, mechlist->base,
227
- NULL, data, ndata, &chosenmech);
228
- switch (saslerr) {
229
- case SASL_OK:
230
- ctx->nmech = strlen(chosenmech);
231
- if (! (ctx->mech = strdup(chosenmech)) ) {
232
- set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
233
- return -1;
234
- }
235
- return 0;
236
- case SASL_NOMECH:
237
- lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "Server does not support SASL (no mechanisms supported)", SESSREQ_LOGID(sreq));
238
- return 1;
239
- break;
240
- default:
241
- lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "cbsasl_client_start returned %d", SESSREQ_LOGID(sreq), saslerr);
242
- set_error_ex(sreq, LCB_EINTERNAL, "Couldn't start SASL client");
243
- return -1;
244
- }
245
- }
246
-
247
- /**
248
- * Given the specific mechanisms, send the auth packet to the server.
249
- */
250
- static int
251
- send_sasl_auth(neg_PENDING *pend, const char *sasl_data, unsigned ndata)
252
- {
253
- mc_pSESSINFO ctx = pend->inner;
254
- protocol_binary_request_no_extras req;
255
- protocol_binary_request_header *hdr = &req.message.header;
256
- memset(&req, 0, sizeof(req));
257
-
258
- hdr->request.magic = PROTOCOL_BINARY_REQ;
259
- hdr->request.opcode = PROTOCOL_BINARY_CMD_SASL_AUTH;
260
- hdr->request.keylen = htons((lcb_uint16_t)ctx->nmech);
261
- hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES;
262
- hdr->request.bodylen = htonl((lcb_uint32_t)ndata + ctx->nmech);
263
-
264
- lcbio_ctx_put(pend->ctx, req.bytes, sizeof(req.bytes));
265
- lcbio_ctx_put(pend->ctx, ctx->mech, ctx->nmech);
266
- lcbio_ctx_put(pend->ctx, sasl_data, ndata);
267
- lcbio_ctx_rwant(pend->ctx, 24);
268
- return 0;
269
- }
270
-
271
- static int
272
- send_sasl_step(mc_pSESSREQ sreq, packet_info *packet)
273
- {
274
- protocol_binary_request_no_extras req;
275
- protocol_binary_request_header *hdr = &req.message.header;
276
- cbsasl_error_t saslerr;
277
- const char *step_data;
278
- unsigned int ndata;
279
- mc_pSESSINFO ctx = sreq->inner;
280
-
281
- saslerr = cbsasl_client_step(
282
- ctx->sasl, packet->payload, PACKET_NBODY(packet), NULL, &step_data,
283
- &ndata);
284
-
285
- if (saslerr != SASL_CONTINUE) {
286
- set_error_ex(sreq, LCB_EINTERNAL, "Unable to perform SASL STEP");
287
- return -1;
288
- }
289
-
290
- memset(&req, 0, sizeof(req));
291
- hdr->request.magic = PROTOCOL_BINARY_REQ;
292
- hdr->request.opcode = PROTOCOL_BINARY_CMD_SASL_STEP;
293
- hdr->request.keylen = htons((uint16_t)ctx->nmech);
294
- hdr->request.bodylen = htonl((uint32_t)ndata + ctx->nmech);
295
- hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES;
296
-
297
- lcbio_ctx_put(sreq->ctx, req.bytes, sizeof(req.bytes));
298
- lcbio_ctx_put(sreq->ctx, ctx->mech, ctx->nmech);
299
- lcbio_ctx_put(sreq->ctx, step_data, ndata);
300
- lcbio_ctx_rwant(sreq->ctx, 24);
301
- return 0;
302
- }
303
-
304
- static int
305
- send_hello(mc_pSESSREQ sreq)
306
- {
307
- protocol_binary_request_no_extras req;
308
- protocol_binary_request_header *hdr = &req.message.header;
309
- unsigned ii;
310
- const char *external_id = "";
311
- const char *comma = "";
312
- char client_id[200] = { 0 };
313
- lcb_U16 features[MEMCACHED_TOTAL_HELLO_FEATURES];
314
- unsigned nfeatures = 0;
315
- size_t nclistr;
316
-
317
- features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TLS;
318
- if (sreq->inner->settings->tcp_nodelay) {
319
- features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TCPNODELAY;
320
- }
321
-
322
- #ifndef LCB_NO_SNAPPY
323
- if (sreq->inner->settings->compressopts != LCB_COMPRESS_NONE) {
324
- features[nfeatures++] = PROTOCOL_BINARY_FEATURE_DATATYPE;
325
- }
326
- #endif
327
-
328
- if (sreq->inner->settings->fetch_mutation_tokens) {
329
- features[nfeatures++] = PROTOCOL_BINARY_FEATURE_MUTATION_SEQNO;
330
- }
331
-
332
- if (sreq->inner->settings->client_string) {
333
- external_id = sreq->inner->settings->client_string;
334
- comma = ", ";
335
- }
336
-
337
- snprintf(client_id, 199, "libcouchbase/%s%s%s",
338
- LCB_VERSION_STRING, comma, external_id);
339
- nclistr = strlen(client_id);
340
-
341
- memset(&req, 0, sizeof req);
342
- hdr->request.opcode = PROTOCOL_BINARY_CMD_HELLO;
343
- hdr->request.magic = PROTOCOL_BINARY_REQ;
344
- hdr->request.keylen = htons((lcb_U16)nclistr);
345
- hdr->request.bodylen = htonl((lcb_U32)(nclistr+ (sizeof features[0]) * nfeatures));
346
- hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES;
347
-
348
- lcbio_ctx_put(sreq->ctx, req.bytes, sizeof req.bytes);
349
- lcbio_ctx_put(sreq->ctx, client_id, strlen(client_id));
350
- for (ii = 0; ii < nfeatures; ii++) {
351
- lcb_U16 tmp = htons(features[ii]);
352
- lcbio_ctx_put(sreq->ctx, &tmp, sizeof tmp);
353
- }
354
- lcbio_ctx_rwant(sreq->ctx, 24);
355
- return 0;
356
- }
357
-
358
- static int
359
- parse_hello(mc_pSESSREQ sreq, packet_info *packet)
360
- {
361
- /* some caps */
362
- const char *cur;
363
- const char *payload = PACKET_BODY(packet);
364
- const char *limit = payload + PACKET_NBODY(packet);
365
- for (cur = payload; cur < limit; cur += 2) {
366
- lcb_U16 tmp;
367
- memcpy(&tmp, cur, sizeof(tmp));
368
- tmp = ntohs(tmp);
369
- lcb_log(LOGARGS(sreq, DEBUG), SESSREQ_LOGFMT "Found feature 0x%x (%s)", SESSREQ_LOGID(sreq), tmp, protocol_feature_2_text(tmp));
370
- sreq->inner->features[tmp] = 1;
371
- }
372
- return 0;
373
- }
374
-
375
-
376
- typedef enum {
377
- SREQ_S_WAIT,
378
- SREQ_S_AUTHDONE,
379
- SREQ_S_HELLODONE,
380
- SREQ_S_ERROR
381
- } sreq_STATE;
382
-
383
- /**
384
- * It's assumed the server buffers will be reset upon close(), so we must make
385
- * sure to _not_ release the ringbuffer if that happens.
386
- */
387
- static void
388
- handle_read(lcbio_CTX *ioctx, unsigned nb)
389
- {
390
- mc_pSESSREQ sreq = lcbio_ctx_data(ioctx);
391
- packet_info info;
392
- unsigned required;
393
- uint16_t status;
394
- sreq_STATE state = SREQ_S_WAIT;
395
- int rc;
396
-
397
- GT_NEXT_PACKET:
398
-
399
- memset(&info, 0, sizeof(info));
400
- rc = lcb_pktinfo_ectx_get(&info, ioctx, &required);
401
- if (rc == 0) {
402
- LCBIO_CTX_RSCHEDULE(ioctx, required);
403
- return;
404
- } else if (rc < 0) {
405
- state = SREQ_S_ERROR;
406
- }
407
-
408
- status = PACKET_STATUS(&info);
409
-
410
- switch (PACKET_OPCODE(&info)) {
411
- case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: {
412
- lcb_string str;
413
- int saslrc;
414
- const char *mechlist_data;
415
- unsigned int nmechlist_data;
416
- if (lcb_string_init(&str)) {
417
- set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
418
- state = SREQ_S_ERROR;
419
- break;
420
- }
421
-
422
- if (lcb_string_append(&str, info.payload, PACKET_NBODY(&info))) {
423
- lcb_string_release(&str);
424
- set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
425
- state = SREQ_S_ERROR;
426
- break;
427
- }
428
-
429
- saslrc = set_chosen_mech(sreq, &str, &mechlist_data, &nmechlist_data);
430
- if (saslrc == 0) {
431
- if (0 == send_sasl_auth(sreq, mechlist_data, nmechlist_data)) {
432
- state = SREQ_S_WAIT;
433
- } else {
434
- state = SREQ_S_ERROR;
435
- }
436
-
437
- } else if (saslrc < 0) {
438
- state = SREQ_S_ERROR;
439
-
440
- } else {
441
- state = SREQ_S_HELLODONE;
442
- }
443
- lcb_string_release(&str);
444
- break;
445
- }
446
-
447
- case PROTOCOL_BINARY_CMD_SASL_AUTH: {
448
- if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
449
- send_hello(sreq);
450
- state = SREQ_S_AUTHDONE;
451
- break;
452
- }
453
-
454
- if (status != PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
455
- set_error_ex(sreq, LCB_AUTH_ERROR, "SASL AUTH failed");
456
- state = SREQ_S_ERROR;
457
- break;
458
- }
459
- if (send_sasl_step(sreq, &info) == 0 && send_hello(sreq) == 0) {
460
- state = SREQ_S_WAIT;
461
- } else {
462
- state = SREQ_S_ERROR;
463
- }
464
- break;
465
- }
466
-
467
- case PROTOCOL_BINARY_CMD_SASL_STEP: {
468
- if (status != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
469
- lcb_log(LOGARGS(sreq, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(sreq), status);
470
- set_error_ex(sreq, LCB_AUTH_ERROR, "SASL Step Failed");
471
- state = SREQ_S_ERROR;
472
- } else {
473
- /* Wait for pipelined HELLO response */
474
- state = SREQ_S_AUTHDONE;
475
- }
476
- break;
477
- }
478
-
479
- case PROTOCOL_BINARY_CMD_HELLO: {
480
- state = SREQ_S_HELLODONE;
481
- if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
482
- parse_hello(sreq, &info);
483
- } else if (status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ||
484
- status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED) {
485
- lcb_log(LOGARGS(sreq, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(sreq));
486
- /* nothing */
487
- } else {
488
- set_error_ex(sreq, LCB_PROTOCOL_ERROR, "Hello response unexpected");
489
- state = SREQ_S_ERROR;
490
- }
491
- break;
492
- }
493
-
494
- default: {
495
- state = SREQ_S_ERROR;
496
- lcb_log(LOGARGS(sreq, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(sreq), PACKET_OPCODE(&info), PACKET_STATUS(&info));
497
- set_error_ex(sreq, LCB_NOT_SUPPORTED, "Received unknown response");
498
- break;
499
- }
500
- }
501
-
502
- lcb_pktinfo_ectx_done(&info, ioctx);
503
- if (sreq->err != LCB_SUCCESS) {
504
- bail_pending(sreq);
505
- } else if (state == SREQ_S_ERROR) {
506
- set_error_ex(sreq, LCB_ERROR, "FIXME: Error code set without description");
507
- } else if (state == SREQ_S_HELLODONE) {
508
- negotiation_success(sreq);
509
- } else {
510
- goto GT_NEXT_PACKET;
511
- }
512
-
513
- (void)nb;
514
- }
515
-
516
- static void
517
- handle_ioerr(lcbio_CTX *ctx, lcb_error_t err)
518
- {
519
- mc_pSESSREQ sreq = lcbio_ctx_data(ctx);
520
- set_error_ex(sreq, err, "IO Error");
521
- bail_pending(sreq);
522
- }
523
-
524
- static void
525
- cleanup_negotiated(mc_pSESSINFO ctx)
526
- {
527
- if (ctx->sasl) {
528
- cbsasl_dispose(&ctx->sasl);
529
- }
530
- if (ctx->mech) {
531
- free(ctx->mech);
532
- }
533
- free(ctx);
534
- }
535
-
536
- static void
537
- cleanup_pending(mc_pSESSREQ sreq)
538
- {
539
- if (sreq->inner) {
540
- cleanup_negotiated(sreq->inner);
541
- sreq->inner = NULL;
542
- }
543
- if (sreq->timer) {
544
- lcbio_timer_destroy(sreq->timer);
545
- sreq->timer = NULL;
546
- }
547
- if (sreq->ctx) {
548
- lcbio_ctx_close(sreq->ctx, NULL, NULL);
549
- sreq->ctx = NULL;
550
- }
551
- free(sreq);
552
- }
553
-
554
- void
555
- mc_sessreq_cancel(mc_pSESSREQ sreq)
556
- {
557
- cleanup_pending(sreq);
558
- }
559
-
560
- mc_pSESSREQ
561
- mc_sessreq_start(lcbio_SOCKET *sock, lcb_settings *settings,
562
- uint32_t tmo, lcbio_CONNDONE_cb callback, void *data)
563
- {
564
- lcb_error_t err;
565
- cbsasl_error_t saslerr;
566
- protocol_binary_request_no_extras req;
567
- const lcb_host_t *curhost;
568
- struct lcbio_NAMEINFO nistrs;
569
- mc_pSESSREQ sreq;
570
- mc_pSESSINFO sasl;
571
- lcbio_CTXPROCS procs;
572
-
573
- if ((sreq = calloc(1, sizeof(*sreq))) == NULL) {
574
- return NULL;
575
- }
576
-
577
- if ((sasl = calloc(1, sizeof(*sasl))) == NULL) {
578
- cleanup_pending(sreq);
579
- return NULL;
580
- }
581
-
582
- procs.cb_err = handle_ioerr;
583
- procs.cb_read = handle_read;
584
-
585
- lcbio_get_nameinfo(sock, &nistrs);
586
- sreq->cb = callback;
587
- sreq->data = data;
588
- sreq->inner = sasl;
589
- sreq->timer = lcbio_timer_new(sock->io, sreq, timeout_handler);
590
-
591
- if ((err = lcbio_sslify_if_needed(sock, settings)) != LCB_SUCCESS) {
592
- set_error_ex(sreq, err, "Couldn't initialize SSL on socket");
593
- lcbio_async_signal(sreq->timer);
594
- return sreq;
595
- }
596
-
597
- sreq->ctx = lcbio_ctx_new(sock, sreq, &procs);
598
- sreq->ctx->subsys = "sasl";
599
-
600
- if (tmo) {
601
- lcbio_timer_rearm(sreq->timer, tmo);
602
- }
603
-
604
- sasl->base.id = LCBIO_PROTOCTX_SESSINFO;
605
- sasl->base.dtor = (void (*)(struct lcbio_PROTOCTX *))cleanup_negotiated;
606
- sasl->settings = settings;
607
-
608
- err = setup_sasl_params(sasl);
609
- if (err != LCB_SUCCESS) {
610
- cleanup_pending(sreq);
611
- return NULL;
612
- }
613
-
614
-
615
- curhost = lcbio_get_host(sock);
616
- saslerr = cbsasl_client_new(
617
- "couchbase", curhost->host, nistrs.local, nistrs.remote,
618
- sasl->sasl_callbacks, 0, &sasl->sasl);
619
-
620
- if (saslerr != SASL_OK) {
621
- cleanup_pending(sreq);
622
- return NULL;
623
- }
624
-
625
- memset(&req, 0, sizeof(req));
626
- req.message.header.request.magic = PROTOCOL_BINARY_REQ;
627
- req.message.header.request.opcode = PROTOCOL_BINARY_CMD_SASL_LIST_MECHS;
628
- req.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
629
- req.message.header.request.bodylen = 0;
630
- req.message.header.request.keylen = 0;
631
- req.message.header.request.opaque = 0;
632
-
633
- lcbio_ctx_put(sreq->ctx, req.bytes, sizeof(req.bytes));
634
- LCBIO_CTX_RSCHEDULE(sreq->ctx, 24);
635
- return sreq;
636
- }
637
-
638
- mc_pSESSINFO
639
- mc_sess_get(lcbio_SOCKET *sock)
640
- {
641
- return (void *)lcbio_protoctx_get(sock, LCBIO_PROTOCTX_SESSINFO);
642
- }
643
-
644
- const char *
645
- mc_sess_get_saslmech(mc_pSESSINFO info)
646
- {
647
- return info->mech;
648
- }
649
-
650
- int
651
- mc_sess_chkfeature(mc_pSESSINFO info, lcb_U16 feature)
652
- {
653
- if (feature > MEMCACHED_TOTAL_HELLO_FEATURES) {
654
- return 0;
655
- }
656
- return info->features[feature];
657
- }