LIBCOUCHBASE_API lcb_error_t lcb_cbflush3(lcb_t instance, const void *cookie, const lcb_CMDBASE *cmd) { lcb_http_request_t htr; lcb_CMDHTTP htcmd = { 0 }; lcb_string urlpath; lcb_error_t rc; (void)cmd; lcb_string_init(&urlpath); lcb_string_appendz(&urlpath, "/pools/default/buckets/"); lcb_string_appendz(&urlpath, LCBT_SETTING(instance, bucket)); lcb_string_appendz(&urlpath, "/controller/doFlush"); htcmd.type = LCB_HTTP_TYPE_MANAGEMENT; htcmd.method = LCB_HTTP_METHOD_POST; htcmd.reqhandle = &htr; LCB_CMD_SET_KEY(&htcmd, urlpath.base, urlpath.nused); rc = lcb_http3(instance, cookie, &htcmd); lcb_string_release(&urlpath); if (rc != LCB_SUCCESS) { return rc; } lcb_htreq_setcb(htr, flush_cb); return LCB_SUCCESS; }
static const char * mk_scratch_host(lcb_t instance, const lcb_host_t *host) { if (!ensure_scratch(instance, strlen(host->host)+strlen(host->port)+2)) { return NULL; } lcb_string_appendz(instance->scratch, host->host); lcb_string_appendz(instance->scratch, ":"); lcb_string_appendz(instance->scratch, host->port); return instance->scratch->base; }
static lcb_error_t parse_body(struct htvb_st *vbs, int *done) { lcb_error_t err = LCB_BUSY; char *term; if ((err = parse_chunk(vbs)) != LCB_SUCCESS) { *done = 1; /* no data */ lcb_assert(err == LCB_BUSY); return err; } if (lcb_string_append(&vbs->input, vbs->chunk.base, vbs->chunk_size)) { return LCB_CLIENT_ENOMEM; } lcb_string_erase_end(&vbs->input, 2); lcb_string_erase_beginning(&vbs->chunk, vbs->chunk_size); vbs->chunk_size = (lcb_size_t) - 1; if (vbs->chunk.nused > 0) { *done = 0; } term = strstr(vbs->input.base, "\n\n\n\n"); if (term != NULL) { lcb_string tmp; lcb_error_t ret; /** Next input */ lcb_string_init(&tmp); lcb_string_appendz(&tmp, term + 4); *term = '\0'; ret = set_next_config(vbs); /** Now, erase everything until the end of the 'term' */ if (vbs->input.base) { lcb_string_release(&vbs->input); } lcb_string_transfer(&tmp, &vbs->input); return ret; } return err; }
static void sanitize_config( const lcb_string *src, const char *host, lcb_string *dst) { char *cur = src->base, *last = src->base; while ((cur = strstr(cur, HOST_TOKEN))) { lcb_string_append(dst, last, cur-last); lcb_string_appendz(dst, host); cur += sizeof(HOST_TOKEN)-1; last = cur; } lcb_string_append(dst, last, src->base + src->nalloc - last); }
/** * Try to parse the headers in the input chunk. * * @param instance the instance containing the data * @return 0 success, 1 we need more data, -1 incorrect response */ static lcb_error_t parse_header(struct htvb_st *vbs, lcb_type_t btype) { int response_code; lcb_string *chunk = &vbs->chunk; char *ptr = strstr(chunk->base, "\r\n\r\n"); if (ptr != NULL) { *ptr = '\0'; ptr += 4; } else if ((ptr = strstr(chunk->base, "\n\n")) != NULL) { *ptr = '\0'; ptr += 2; } else { /* We need more data! */ return LCB_BUSY; } /* parse the headers I care about... */ if (sscanf(chunk->base, "HTTP/1.1 %d", &response_code) != 1) { return LCB_PROTOCOL_ERROR; } else if (response_code != 200) { switch (response_code) { case 401: return LCB_AUTH_ERROR; case 404: return LCB_BUCKET_ENOENT; default: return LCB_PROTOCOL_ERROR; break; } } /** TODO: Isn't a vBucket config only for BUCKET types? */ if (btype == LCB_TYPE_BUCKET && strstr(chunk->base, "Transfer-Encoding: chunked") == NULL && strstr(chunk->base, "Transfer-encoding: chunked") == NULL) { return LCB_PROTOCOL_ERROR; } lcb_string_appendz(&vbs->header, chunk->base); /* realign remaining data.. */ lcb_string_erase_beginning(chunk, ptr-chunk->base); vbs->chunk_size = (lcb_size_t) - 1; return LCB_SUCCESS; }
/** * Called to retrive the mechlist from the packet. * @return 0 to continue authentication, 1 if no authentication needed, or * -1 on error. */ static int set_chosen_mech(mc_pSESSREQ sreq, lcb_string *mechlist, const char **data, unsigned int *ndata) { cbsasl_error_t saslerr; const char *chosenmech; mc_pSESSINFO ctx = sreq->inner; lcb_assert(sreq->inner); if (ctx->settings->sasl_mech_force) { char *forcemech = ctx->settings->sasl_mech_force; if (!strstr(mechlist->base, forcemech)) { /** Requested mechanism not found */ set_error_ex(sreq, LCB_SASLMECH_UNAVAILABLE, mechlist->base); return -1; } lcb_string_clear(mechlist); if (lcb_string_appendz(mechlist, forcemech)) { set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL); return -1; } } saslerr = cbsasl_client_start(ctx->sasl, mechlist->base, NULL, data, ndata, &chosenmech); switch (saslerr) { case SASL_OK: ctx->nmech = strlen(chosenmech); if (! (ctx->mech = strdup(chosenmech)) ) { set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL); return -1; } return 0; case SASL_NOMECH: lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "Server does not support SASL (no mechanisms supported)", SESSREQ_LOGID(sreq)); return 1; break; default: lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "cbsasl_client_start returned %d", SESSREQ_LOGID(sreq), saslerr); set_error_ex(sreq, LCB_EINTERNAL, "Couldn't start SASL client"); return -1; } }
LIBCOUCHBASE_API const char * lcb_get_node(lcb_t instance, lcb_GETNODETYPE type, unsigned ix) { if (type & LCB_NODE_HTCONFIG) { if (type & LCB_NODE_CONNECTED) { const lcb_host_t *host = lcb_confmon_get_rest_host(instance->confmon); if (host) { return mk_scratch_host(instance, host); } else { return return_badhost(type); } } else { /* Retrieve one from the vbucket configuration */ lcbvb_CONFIG *vbc = LCBT_VBCONFIG(instance); lcbvb_SVCMODE mode; const char *hp = NULL; if (LCBT_SETTING(instance, sslopts) & LCB_SSL_ENABLED) { mode = LCBVB_SVCMODE_SSL; } else { mode = LCBVB_SVCMODE_PLAIN; } if (instance->type == LCB_TYPE_BUCKET) { if (vbc) { ix %= LCBVB_NSERVERS(vbc); hp = lcbvb_get_hostport(vbc, ix, LCBVB_SVCTYPE_MGMT, mode); } else if ((type & LCB_NODE_NEVERNULL) == 0) { return NULL; } } if (hp == NULL && instance->ht_nodes && instance->ht_nodes->nentries) { ix %= instance->ht_nodes->nentries; hostlist_ensure_strlist(instance->ht_nodes); hp = instance->ht_nodes->slentries[ix]; } if (!hp) { if ((hp = return_badhost(type)) == NULL) { return NULL; } } if (!ensure_scratch(instance, strlen(hp)+1)) { return NULL; } lcb_string_appendz(instance->scratch, hp); return instance->scratch->base; } } else if (type & (LCB_NODE_DATA|LCB_NODE_VIEWS)) { const mc_SERVER *server; ix %= LCBT_NSERVERS(instance); server = LCBT_GET_SERVER(instance, ix); if ((type & LCB_NODE_CONNECTED) && server->connctx == NULL) { return return_badhost(type); } if (server->curhost == NULL) { return return_badhost(type); } /* otherwise, return the actual host:port of the server */ if (type & LCB_NODE_DATA) { return mk_scratch_host(instance, server->curhost); } else { return server->viewshost; } } else { return NULL; /* don't know the type */ } }
lcb_error_t hostlist_add_string(hostlist_t hostlist, const char *spec, int speclen, int deflport) { lcb_error_t err = LCB_SUCCESS; lcb_string str; char *delim; char *curstart; if (speclen < 0) { speclen = strlen(spec); } if (lcb_string_init(&str)) { return LCB_CLIENT_ENOMEM; } if (lcb_string_append(&str, spec, speclen)) { lcb_string_release(&str); return LCB_CLIENT_ENOMEM; } if (!str.nused) { lcb_string_release(&str); return LCB_SUCCESS; } if (str.base[str.nused-1] != ';') { if (lcb_string_appendz(&str, ";")) { lcb_string_release(&str); return LCB_CLIENT_ENOMEM; } } curstart = str.base; while ( (delim = strstr(curstart, ";"))) { lcb_host_t curhost; lcb_size_t curlen; if (delim == curstart) { curstart++; continue; } /** { 'f', 'o', 'o', ';' } */ curlen = delim - curstart; err = lcb_host_parse(&curhost, curstart, curlen, deflport); if (err != LCB_SUCCESS) { break; } err = hostlist_add_host(hostlist, &curhost); if (err != LCB_SUCCESS) { break; } curstart = delim + 1; } lcb_string_release(&str); return err; }