libcouchbase 0.0.4 → 0.0.5

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.
@@ -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
- }