/** * build headers from request * * @param req * @param headersp * * @return */ dpl_status_t dpl_cdmi_req_build(const dpl_req_t *req, dpl_dict_t **headersp, char **body_strp, int *body_lenp) { dpl_dict_t *headers = NULL; int ret, ret2; char *method = dpl_method_str(req->method); json_object *body_obj = NULL; char *body_str = NULL; int body_len = 0; char buf[256]; DPL_TRACE(req->ctx, DPL_TRACE_REQ, "req_build method=%s bucket=%s resource=%s subresource=%s", method, req->bucket, req->resource, req->subresource); headers = dpl_dict_new(13); if (NULL == headers) { ret = DPL_ENOMEM; goto end; } /* * per method headers */ if (DPL_METHOD_GET == req->method) { //XXX ranges, conditions switch (req->object_type) { case DPL_FTYPE_UNDEF: //do nothing break ; case DPL_FTYPE_ANY: ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_ANY, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } break ; case DPL_FTYPE_REG: ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_OBJECT, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } break ; case DPL_FTYPE_DIR: ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_CONTAINER, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } break ; case DPL_FTYPE_CAP: ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_CAPABILITY, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } break ; } } else if (DPL_METHOD_PUT == req->method || DPL_METHOD_POST == req->method) { body_obj = json_object_new_object(); if (NULL == body_obj) { ret = DPL_ENOMEM; goto end; } if (NULL != req->cache_control) { ret2 = dpl_dict_add(headers, "Cache-Control", req->cache_control, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != req->content_disposition) { ret2 = dpl_dict_add(headers, "Content-Disposition", req->content_disposition, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != req->content_encoding) { ret2 = dpl_dict_add(headers, "Content-Encoding", req->content_encoding, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (!(req->behavior_flags & DPL_BEHAVIOR_HTTP_COMPAT)) { ret2 = add_metadata_to_json_body(req->metadata, body_obj); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL != req->chunk) { ret2 = add_data_to_json_body(req->chunk, body_obj); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } pthread_mutex_lock(&req->ctx->lock); body_str = (char *) json_object_to_json_string(body_obj); pthread_mutex_unlock(&req->ctx->lock); if (NULL == body_str) { ret = DPL_ENOMEM; goto end; } body_len = strlen(body_str); snprintf(buf, sizeof (buf), "%u", body_len); ret2 = dpl_dict_add(headers, "Content-Length", buf, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } else { snprintf(buf, sizeof (buf), "%u", req->chunk->len); ret2 = dpl_dict_add(headers, "Content-Length", buf, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } if (req->behavior_flags & DPL_BEHAVIOR_EXPECT) { ret2 = dpl_dict_add(headers, "Expect", "100-continue", 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } switch (req->object_type) { case DPL_FTYPE_UNDEF: //do nothing break ; case DPL_FTYPE_ANY: //error ? break ; case DPL_FTYPE_REG: ret2 = dpl_dict_add(headers, "Content-Type", DPL_CDMI_CONTENT_TYPE_OBJECT, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } break ; case DPL_FTYPE_DIR: ret2 = dpl_dict_add(headers, "Content-Type", DPL_CDMI_CONTENT_TYPE_CONTAINER, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } break ; case DPL_FTYPE_CAP: ret2 = dpl_dict_add(headers, "Content-Type", DPL_CDMI_CONTENT_TYPE_CAPABILITY, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } break ; } } else if (DPL_METHOD_DELETE == req->method) { } else { ret = DPL_EINVAL; goto end; } /* * common headers */ if (!(req->behavior_flags & DPL_BEHAVIOR_HTTP_COMPAT)) { ret2 = dpl_dict_add(headers, "X-CDMI-Specification-Version", "1.0.1", 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (req->behavior_flags & DPL_BEHAVIOR_VIRTUAL_HOSTING) { char host[1024]; snprintf(host, sizeof (host), "%s.%s", req->bucket, req->ctx->host); ret2 = dpl_dict_add(headers, "Host", host, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } else { ret2 = dpl_dict_add(headers, "Host", req->ctx->host, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } if (req->behavior_flags & DPL_BEHAVIOR_KEEP_ALIVE) { ret2 = dpl_dict_add(headers, "Connection", "keep-alive", 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } ret2 = add_authorization_to_headers(req, headers); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL != body_strp) { if (NULL == body_str) { *body_strp = NULL; } else { *body_strp = strdup(body_str); if (NULL == body_strp) { ret = DPL_ENOMEM; goto end; } } } if (NULL != body_lenp) *body_lenp = body_len; if (NULL != headersp) { *headersp = headers; headers = NULL; //consume it } ret = DPL_SUCCESS; end: if (NULL != body_obj) json_object_put(body_obj); if (NULL != headers) dpl_dict_free(headers); return ret; }
dpl_status_t dpl_s3_head_raw(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, dpl_dict_t **metadatap, 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; int connection_close = 0; dpl_dict_t *headers_request = NULL; dpl_dict_t *headers_reply = NULL; dpl_req_t *req = NULL; dpl_s3_req_mask_t req_mask = 0u; DPL_TRACE(ctx, DPL_TRACE_BACKEND, ""); req = dpl_req_new(ctx); if (NULL == req) { ret = DPL_ENOMEM; goto end; } dpl_req_set_method(req, DPL_METHOD_HEAD); 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_s3_add_authorization_to_headers(req, headers_request, NULL, NULL); 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"); connection_close = 1; ret = ret2; goto end; } ret2 = dpl_read_http_reply(conn, 0, NULL, NULL, &headers_reply, &connection_close); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL != metadatap) { *metadatap = headers_reply; headers_reply = NULL; } ret = DPL_SUCCESS; end: if (NULL != conn) { if (1 == connection_close) dpl_conn_terminate(conn); else dpl_conn_release(conn); } if (NULL != headers_reply) dpl_dict_free(headers_reply); 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; }
dpl_status_t dpl_sproxyd_put_internal(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, const dpl_dict_t *metadata, const dpl_sysmd_t *sysmd, const char *data_buf, unsigned int data_len, int mdonly, 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; int connection_close = 0; dpl_dict_t *headers_request = NULL; dpl_dict_t *headers_reply = NULL; dpl_req_t *req = NULL; dpl_sproxyd_req_mask_t req_mask = 0u; dpl_dict_t *query_params = NULL; uint32_t force_version = -1; DPL_TRACE(ctx, DPL_TRACE_BACKEND, ""); req = dpl_req_new(ctx); if (NULL == req) { ret = DPL_ENOMEM; goto end; } dpl_req_set_method(req, DPL_METHOD_PUT); 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; } } dpl_req_set_object_type(req, object_type); if (NULL != condition) { dpl_req_set_condition(req, condition); } if (option) { if (option->mask & DPL_OPTION_CONSISTENT) req_mask |= DPL_SPROXYD_REQ_CONSISTENT; if (option->mask & DPL_OPTION_EXPECT_VERSION) { req_mask = DPL_SPROXYD_REQ_EXPECT_VERSION; query_params = dpl_dict_new(13); if (NULL == query_params) { ret = DPL_ENOMEM; goto end; } ret2 = dpl_dict_add(query_params, "version", option->expect_version, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (option->mask & DPL_OPTION_FORCE_VERSION) { req_mask = DPL_SPROXYD_REQ_FORCE_VERSION; force_version = strtoul(option->force_version, NULL, 0); } } if (mdonly) { req_mask |= DPL_SPROXYD_REQ_MD_ONLY; } else { dpl_req_set_data(req, data_buf, data_len); } dpl_req_add_behavior(req, DPL_BEHAVIOR_MD5); if (NULL != metadata) { ret2 = dpl_req_add_metadata(req, metadata); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } //build request ret2 = dpl_sproxyd_req_build(req, req_mask, force_version, &headers_request); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } //contact default host dpl_req_rm_behavior(req, DPL_BEHAVIOR_VIRTUAL_HOSTING); 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, query_params, 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++; //buffer iov[n_iov].iov_base = (void *)data_buf; iov[n_iov].iov_len = data_len; 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"); connection_close = 1; ret = ret2; goto end; } ret2 = dpl_read_http_reply(conn, 1, NULL, NULL, &headers_reply, &connection_close); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret = DPL_SUCCESS; end: if (NULL != conn) { if (1 == connection_close) dpl_conn_terminate(conn); else dpl_conn_release(conn); } if (NULL != headers_reply) dpl_dict_free(headers_reply); if (NULL != headers_request) dpl_dict_free(headers_request); if (NULL != query_params) dpl_dict_free(query_params); if (NULL != req) dpl_req_free(req); DPL_TRACE(ctx, DPL_TRACE_BACKEND, "ret=%d", ret); return ret; }