/** * read http reply simple version * * @param fd * @param expect_data * @param buffer_provided if 1 then caller provides buffer and length in *data_bufp and *data_lenp * @param data_bufp caller must free it * @param data_lenp * @param headersp caller must free it * * @return dpl_status */ dpl_status_t dpl_read_http_reply_ext(dpl_conn_t *conn, int expect_data, int buffer_provided, char **data_bufp, unsigned int *data_lenp, dpl_dict_t **headersp, int *connection_closep) { int ret, ret2; struct httreply_conven hc; int connection_close = 0; int http_status; memset(&hc, 0, sizeof (hc)); if (buffer_provided) { hc.data_buf = *data_bufp; hc.max_len = *data_lenp; } ret2 = dpl_read_http_reply_buffered(conn, expect_data, &http_status, cb_httpreply_header, buffer_provided ? cb_httpreply_buffer_noalloc : cb_httpreply_buffer, &hc); if (DPL_SUCCESS != ret2) { //on I/O failure close connection connection_close = 1; //blacklist host dpl_blacklist_host(conn->ctx, conn->host, conn->port); ret = ret2; goto end; } //connection_close might explicitely be requested if (dpl_connection_close(hc.headers)) connection_close = 1; //some servers does not send explicit connection information and does not support keep alive if (!conn->ctx->keep_alive) connection_close = 1; //blacklist host with server errors if (http_status / 100 == 5) dpl_blacklist_host(conn->ctx, conn->host, conn->port); //map http_status to relevant value ret = dpl_map_http_status(http_status); printf("http_status: %d\n", http_status); end: if (NULL != data_bufp) { *data_bufp = hc.data_buf; hc.data_buf = NULL; //consumed } if (NULL != data_lenp) *data_lenp = hc.data_len; if (NULL != headersp) { *headersp = hc.headers; hc.headers = NULL; //consumed } //if not consumed if (NULL != hc.data_buf) free(hc.data_buf); if (NULL != hc.headers) dpl_dict_free(hc.headers); if (NULL != connection_closep) *connection_closep = connection_close; return ret; }
dpl_status_t dpl_s3_get_buffered(dpl_ctx_t *ctx, const char *bucket, const char *resource, const char *subresource, const dpl_option_t *option, dpl_ftype_t object_type, const dpl_condition_t *condition, const dpl_range_t *range, dpl_metadatum_func_t metadatum_func, dpl_dict_t **metadatap, dpl_sysmd_t *sysmdp, dpl_buffer_func_t buffer_func, void *cb_arg, char **locationp) { int ret, ret2; dpl_conn_t *conn = NULL; char header[dpl_header_size]; u_int header_len; struct iovec iov[10]; int n_iov = 0; dpl_dict_t *headers_request = NULL; dpl_req_t *req = NULL; struct get_conven gc; int http_status; dpl_s3_req_mask_t req_mask = 0u; DPL_TRACE(ctx, DPL_TRACE_BACKEND, ""); memset(&gc, 0, sizeof (gc)); gc.metadata = dpl_dict_new(13); if (NULL == gc.metadata) { ret = DPL_ENOMEM; goto end; } gc.sysmdp = sysmdp; gc.metadatum_func = metadatum_func; gc.buffer_func = buffer_func; gc.cb_arg = cb_arg; req = dpl_req_new(ctx); if (NULL == req) { ret = DPL_ENOMEM; goto end; } dpl_req_set_method(req, DPL_METHOD_GET); if (NULL == bucket) { ret = DPL_EINVAL; goto end; } ret2 = dpl_req_set_bucket(req, bucket); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_req_set_resource(req, resource); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL != subresource) { ret2 = dpl_req_set_subresource(req, subresource); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != condition) { dpl_req_set_condition(req, condition); } //build request ret2 = dpl_s3_req_build(req, req_mask, &headers_request); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_try_connect(ctx, req, &conn); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_add_host_to_headers(req, headers_request); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_req_gen_http_request(ctx, req, headers_request, NULL, header, sizeof (header), &header_len); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } iov[n_iov].iov_base = header; iov[n_iov].iov_len = header_len; n_iov++; //final crlf iov[n_iov].iov_base = "\r\n"; iov[n_iov].iov_len = 2; n_iov++; ret2 = dpl_conn_writev_all(conn, iov, n_iov, conn->ctx->write_timeout); if (DPL_SUCCESS != ret2) { DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "writev failed"); gc.connection_close = 1; ret = ret2; goto end; } ret2 = dpl_read_http_reply_buffered(conn, 1, &http_status, cb_get_header, cb_get_buffer, &gc); if (DPL_SUCCESS != ret2) { DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "read http answer failed"); gc.connection_close = 1; ret = ret2; goto end; } if (!conn->ctx->keep_alive) gc.connection_close = 1; if (NULL != metadatap) { *metadatap = gc.metadata; gc.metadata = NULL; } //map http_status to relevant value ret = dpl_map_http_status(http_status); //caller is responsible for logging the event end: if (NULL != conn) { if (1 == gc.connection_close) dpl_conn_terminate(conn); else dpl_conn_release(conn); } if (NULL != gc.metadata) dpl_dict_free(gc.metadata); if (NULL != headers_request) dpl_dict_free(headers_request); if (NULL != req) dpl_req_free(req); DPL_TRACE(ctx, DPL_TRACE_BACKEND, "ret=%d", ret); return ret; }