s3_default_meta_request.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "aws/s3/private/s3_default_meta_request.h"
  2. #include "aws/s3/private/s3_client_impl.h"
  3. #include "aws/s3/private/s3_meta_request_impl.h"
  4. #include "aws/s3/private/s3_request_messages.h"
  5. #include "aws/s3/private/s3_util.h"
  6. #include <aws/common/string.h>
  7. #include <inttypes.h>
  8. #ifdef _MSC_VER
  9. /* sscanf warning (not currently scanning for strings) */
  10. # pragma warning(disable : 4996)
  11. #endif
  12. static void s_s3_meta_request_default_destroy(struct aws_s3_meta_request *meta_request);
  13. static bool s_s3_meta_request_default_update(
  14. struct aws_s3_meta_request *meta_request,
  15. uint32_t flags,
  16. struct aws_s3_request **out_request);
  17. static int s_s3_meta_request_default_prepare_request(
  18. struct aws_s3_meta_request *meta_request,
  19. struct aws_s3_request *request);
  20. static void s_s3_meta_request_default_request_finished(
  21. struct aws_s3_meta_request *meta_request,
  22. struct aws_s3_request *request,
  23. int error_code);
  24. static struct aws_s3_meta_request_vtable s_s3_meta_request_default_vtable = {
  25. .update = s_s3_meta_request_default_update,
  26. .send_request_finish = aws_s3_meta_request_send_request_finish_handle_async_error,
  27. .prepare_request = s_s3_meta_request_default_prepare_request,
  28. .init_signing_date_time = aws_s3_meta_request_init_signing_date_time_default,
  29. .sign_request = aws_s3_meta_request_sign_request_default,
  30. .finished_request = s_s3_meta_request_default_request_finished,
  31. .destroy = s_s3_meta_request_default_destroy,
  32. .finish = aws_s3_meta_request_finish_default,
  33. };
  34. /* Allocate a new default meta request. */
  35. struct aws_s3_meta_request *aws_s3_meta_request_default_new(
  36. struct aws_allocator *allocator,
  37. struct aws_s3_client *client,
  38. uint64_t content_length,
  39. bool should_compute_content_md5,
  40. const struct aws_s3_meta_request_options *options) {
  41. AWS_PRECONDITION(allocator);
  42. AWS_PRECONDITION(client);
  43. AWS_PRECONDITION(options);
  44. AWS_PRECONDITION(options->message);
  45. struct aws_byte_cursor request_method;
  46. if (aws_http_message_get_request_method(options->message, &request_method)) {
  47. AWS_LOGF_ERROR(
  48. AWS_LS_S3_META_REQUEST,
  49. "Could not create Default Meta Request; could not get request method from message.");
  50. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  51. return NULL;
  52. }
  53. if (content_length > SIZE_MAX) {
  54. AWS_LOGF_ERROR(
  55. AWS_LS_S3_META_REQUEST,
  56. "Could not create Default Meta Request; content length of %" PRIu64 " bytes is too large for platform.",
  57. content_length);
  58. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  59. return NULL;
  60. }
  61. struct aws_s3_meta_request_default *meta_request_default =
  62. aws_mem_calloc(allocator, 1, sizeof(struct aws_s3_meta_request_default));
  63. /* Try to initialize the base type. */
  64. if (aws_s3_meta_request_init_base(
  65. allocator,
  66. client,
  67. 0,
  68. should_compute_content_md5,
  69. options,
  70. meta_request_default,
  71. &s_s3_meta_request_default_vtable,
  72. &meta_request_default->base)) {
  73. AWS_LOGF_ERROR(
  74. AWS_LS_S3_META_REQUEST,
  75. "id=%p Could not initialize base type for Default Meta Request.",
  76. (void *)meta_request_default);
  77. aws_mem_release(allocator, meta_request_default);
  78. return NULL;
  79. }
  80. meta_request_default->content_length = (size_t)content_length;
  81. AWS_LOGF_DEBUG(AWS_LS_S3_META_REQUEST, "id=%p Created new Default Meta Request.", (void *)meta_request_default);
  82. return &meta_request_default->base;
  83. }
  84. static void s_s3_meta_request_default_destroy(struct aws_s3_meta_request *meta_request) {
  85. AWS_PRECONDITION(meta_request);
  86. AWS_PRECONDITION(meta_request->impl);
  87. struct aws_s3_meta_request_default *meta_request_default = meta_request->impl;
  88. aws_mem_release(meta_request->allocator, meta_request_default);
  89. }
  90. /* Try to get the next request that should be processed. */
  91. static bool s_s3_meta_request_default_update(
  92. struct aws_s3_meta_request *meta_request,
  93. uint32_t flags,
  94. struct aws_s3_request **out_request) {
  95. (void)flags;
  96. AWS_PRECONDITION(meta_request);
  97. AWS_PRECONDITION(out_request);
  98. struct aws_s3_meta_request_default *meta_request_default = meta_request->impl;
  99. struct aws_s3_request *request = NULL;
  100. bool work_remaining = false;
  101. /* BEGIN CRITICAL SECTION */
  102. {
  103. aws_s3_meta_request_lock_synced_data(meta_request);
  104. if (!aws_s3_meta_request_has_finish_result_synced(meta_request)) {
  105. /* If the request hasn't been sent, then create and send it now. */
  106. if (!meta_request_default->synced_data.request_sent) {
  107. if (out_request == NULL) {
  108. goto has_work_remaining;
  109. }
  110. request = aws_s3_request_new(meta_request, 0, 1, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS);
  111. AWS_LOGF_DEBUG(
  112. AWS_LS_S3_META_REQUEST,
  113. "id=%p: Meta Request Default created request %p",
  114. (void *)meta_request,
  115. (void *)request);
  116. meta_request_default->synced_data.request_sent = true;
  117. goto has_work_remaining;
  118. }
  119. /* If the request hasn't been completed, then wait for it to be completed. */
  120. if (!meta_request_default->synced_data.request_completed) {
  121. goto has_work_remaining;
  122. }
  123. /* If delivery hasn't been attempted yet for the response body, wait for that to happen. */
  124. if (meta_request->synced_data.num_parts_delivery_completed < 1) {
  125. goto has_work_remaining;
  126. }
  127. goto no_work_remaining;
  128. } else {
  129. /* If we are canceling, and the request hasn't been sent yet, then there is nothing to wait for. */
  130. if (!meta_request_default->synced_data.request_sent) {
  131. goto no_work_remaining;
  132. }
  133. /* If the request hasn't been completed yet, then wait for that to happen. */
  134. if (!meta_request_default->synced_data.request_completed) {
  135. goto has_work_remaining;
  136. }
  137. /* If some parts are still being delivered to the caller, then wait for those to finish. */
  138. if (meta_request->synced_data.num_parts_delivery_completed <
  139. meta_request->synced_data.num_parts_delivery_sent) {
  140. goto has_work_remaining;
  141. }
  142. goto no_work_remaining;
  143. }
  144. has_work_remaining:
  145. work_remaining = true;
  146. no_work_remaining:
  147. if (!work_remaining) {
  148. aws_s3_meta_request_set_success_synced(
  149. meta_request, meta_request_default->synced_data.cached_response_status);
  150. }
  151. aws_s3_meta_request_unlock_synced_data(meta_request);
  152. }
  153. /* END CRITICAL SECTION */
  154. if (work_remaining) {
  155. if (request != NULL) {
  156. AWS_ASSERT(out_request != NULL);
  157. *out_request = request;
  158. }
  159. } else {
  160. AWS_ASSERT(request == NULL);
  161. aws_s3_meta_request_finish(meta_request);
  162. }
  163. return work_remaining;
  164. }
  165. /* Given a request, prepare it for sending based on its description. */
  166. static int s_s3_meta_request_default_prepare_request(
  167. struct aws_s3_meta_request *meta_request,
  168. struct aws_s3_request *request) {
  169. AWS_PRECONDITION(meta_request);
  170. struct aws_s3_meta_request_default *meta_request_default = meta_request->impl;
  171. AWS_PRECONDITION(meta_request_default);
  172. if (meta_request_default->content_length > 0 && request->num_times_prepared == 0) {
  173. aws_byte_buf_init(&request->request_body, meta_request->allocator, meta_request_default->content_length);
  174. if (aws_s3_meta_request_read_body(meta_request, &request->request_body)) {
  175. return AWS_OP_ERR;
  176. }
  177. }
  178. struct aws_http_message *message = aws_s3_message_util_copy_http_message_no_body_all_headers(
  179. meta_request->allocator, meta_request->initial_request_message);
  180. bool flexible_checksum = meta_request->checksum_config.location != AWS_SCL_NONE;
  181. if (!flexible_checksum && meta_request->should_compute_content_md5) {
  182. /* If flexible checksum used, client MUST skip Content-MD5 header computation */
  183. aws_s3_message_util_add_content_md5_header(meta_request->allocator, &request->request_body, message);
  184. }
  185. if (meta_request->checksum_config.validate_response_checksum) {
  186. struct aws_http_headers *headers = aws_http_message_get_headers(message);
  187. aws_http_headers_set(headers, g_request_validation_mode, g_enabled);
  188. }
  189. aws_s3_message_util_assign_body(
  190. meta_request->allocator,
  191. &request->request_body,
  192. message,
  193. &meta_request->checksum_config,
  194. NULL /* out_checksum */);
  195. aws_s3_request_setup_send_data(request, message);
  196. aws_http_message_release(message);
  197. AWS_LOGF_DEBUG(
  198. AWS_LS_S3_META_REQUEST, "id=%p: Meta Request prepared request %p", (void *)meta_request, (void *)request);
  199. return AWS_OP_SUCCESS;
  200. }
  201. static void s_s3_meta_request_default_request_finished(
  202. struct aws_s3_meta_request *meta_request,
  203. struct aws_s3_request *request,
  204. int error_code) {
  205. AWS_PRECONDITION(meta_request);
  206. AWS_PRECONDITION(meta_request->impl);
  207. AWS_PRECONDITION(request);
  208. struct aws_s3_meta_request_default *meta_request_default = meta_request->impl;
  209. AWS_PRECONDITION(meta_request_default);
  210. if (error_code == AWS_ERROR_SUCCESS && meta_request->headers_callback != NULL &&
  211. request->send_data.response_headers != NULL) {
  212. if (meta_request->headers_callback(
  213. meta_request,
  214. request->send_data.response_headers,
  215. request->send_data.response_status,
  216. meta_request->user_data)) {
  217. error_code = aws_last_error_or_unknown();
  218. }
  219. meta_request->headers_callback = NULL;
  220. }
  221. /* BEGIN CRITICAL SECTION */
  222. {
  223. aws_s3_meta_request_lock_synced_data(meta_request);
  224. meta_request_default->synced_data.cached_response_status = request->send_data.response_status;
  225. meta_request_default->synced_data.request_completed = true;
  226. meta_request_default->synced_data.request_error_code = error_code;
  227. if (error_code == AWS_ERROR_SUCCESS) {
  228. aws_s3_meta_request_stream_response_body_synced(meta_request, request);
  229. } else {
  230. aws_s3_meta_request_set_fail_synced(meta_request, request, error_code);
  231. }
  232. aws_s3_meta_request_unlock_synced_data(meta_request);
  233. }
  234. /* END CRITICAL SECTION */
  235. }