@@ -306,6 +306,71 @@ static struct aws_s3_meta_request_vtable s_s3_auto_ranged_put_vtable = {
306306 .pause = s_s3_auto_ranged_put_pause ,
307307};
308308
309+ static int s_init_and_verify_checksum_config_from_headers (
310+ struct checksum_config_storage * checksum_config ,
311+ const struct aws_http_message * message ,
312+ const void * log_id ) {
313+ /* Check if the checksum header was set from the message */
314+ struct aws_http_headers * headers = aws_http_message_get_headers (message );
315+ enum aws_s3_checksum_algorithm header_algo = AWS_SCA_NONE ;
316+ struct aws_byte_cursor header_value ;
317+ AWS_ZERO_STRUCT (header_value );
318+
319+ for (size_t i = 0 ; i < AWS_ARRAY_SIZE (s_checksum_algo_priority_list ); i ++ ) {
320+ enum aws_s3_checksum_algorithm algorithm = s_checksum_algo_priority_list [i ];
321+ const struct aws_byte_cursor algorithm_header_name =
322+ aws_get_http_header_name_from_checksum_algorithm (algorithm );
323+ if (aws_http_headers_get (headers , algorithm_header_name , & header_value ) == AWS_OP_SUCCESS ) {
324+ if (header_algo == AWS_SCA_NONE ) {
325+ header_algo = algorithm ;
326+ } else {
327+ /* If there are multiple checksum headers set, it's malformed request */
328+ AWS_LOGF_ERROR (
329+ AWS_LS_S3_META_REQUEST ,
330+ "id=%p Could not create auto-ranged-put meta request; multiple checksum headers has been set" ,
331+ log_id );
332+ return aws_raise_error (AWS_ERROR_INVALID_ARGUMENT );
333+ }
334+ }
335+ }
336+ if (header_algo == AWS_SCA_NONE ) {
337+ /* No checksum header found, done */
338+ return AWS_OP_SUCCESS ;
339+ }
340+
341+ /* Found the full object checksum from the header, check if it matches the explicit setting from config */
342+ if (checksum_config -> checksum_algorithm != AWS_SCA_NONE && checksum_config -> checksum_algorithm != header_algo ) {
343+ AWS_LOGF_ERROR (
344+ AWS_LS_S3_META_REQUEST ,
345+ "id=%p Could not create auto-ranged-put meta request; checksum config mismatch the checksum from header." ,
346+ log_id );
347+ return aws_raise_error (AWS_ERROR_INVALID_ARGUMENT );
348+ }
349+ AWS_ASSERT (!checksum_config -> has_full_object_checksum );
350+
351+ AWS_LOGF_DEBUG (
352+ AWS_LS_S3_META_REQUEST ,
353+ "id=%p Setting the full-object checksum from header; algorithm: " PRInSTR ", value: " PRInSTR "." ,
354+ log_id ,
355+ AWS_BYTE_CURSOR_PRI (aws_get_checksum_algorithm_name (header_algo )),
356+ AWS_BYTE_CURSOR_PRI (header_value ));
357+ /* Set algo */
358+ checksum_config -> checksum_algorithm = header_algo ;
359+ if (checksum_config -> location == AWS_SCL_NONE ) {
360+ /* Set the checksum location to trailer for the parts, complete MPU will still have the checksum in the header.
361+ * But to keep the data integrity for the parts, we need to set the checksum location to trailer to send the
362+ * parts level checksums.
363+ */
364+ checksum_config -> location = AWS_SCL_TRAILER ;
365+ }
366+
367+ /* Set full object checksum from the header value. */
368+ aws_byte_buf_init_copy_from_cursor (
369+ & checksum_config -> full_object_checksum , checksum_config -> allocator , header_value );
370+ checksum_config -> has_full_object_checksum = true;
371+ return AWS_OP_SUCCESS ;
372+ }
373+
309374/* Allocate a new auto-ranged put meta request */
310375struct aws_s3_meta_request * aws_s3_meta_request_auto_ranged_put_new (
311376 struct aws_allocator * allocator ,
@@ -363,6 +428,11 @@ struct aws_s3_meta_request *aws_s3_meta_request_auto_ranged_put_new(
363428 goto error_clean_up ;
364429 }
365430
431+ if (s_init_and_verify_checksum_config_from_headers (
432+ & auto_ranged_put -> base .checksum_config , options -> message , (void * )& auto_ranged_put -> base )) {
433+ goto error_clean_up ;
434+ }
435+
366436 AWS_LOGF_DEBUG (
367437 AWS_LS_S3_META_REQUEST , "id=%p Created new Auto-Ranged Put Meta Request." , (void * )& auto_ranged_put -> base );
368438
@@ -767,7 +837,7 @@ static int s_verify_part_matches_checksum(
767837 }
768838
769839 struct aws_byte_buf checksum ;
770- if (aws_byte_buf_init (& checksum , allocator , aws_get_digest_size_from_algorithm (algorithm ))) {
840+ if (aws_byte_buf_init (& checksum , allocator , aws_get_digest_size_from_checksum_algorithm (algorithm ))) {
771841 return AWS_OP_ERR ;
772842 }
773843
@@ -776,14 +846,14 @@ static int s_verify_part_matches_checksum(
776846 int return_status = AWS_OP_SUCCESS ;
777847
778848 size_t encoded_len = 0 ;
779- if (aws_base64_compute_encoded_len (aws_get_digest_size_from_algorithm (algorithm ), & encoded_len )) {
849+ if (aws_base64_compute_encoded_len (aws_get_digest_size_from_checksum_algorithm (algorithm ), & encoded_len )) {
780850 AWS_LOGF_ERROR (
781851 AWS_LS_S3_META_REQUEST , "Failed to resume upload. Unable to determine length of encoded checksum." );
782852 return_status = aws_raise_error (AWS_ERROR_S3_RESUME_FAILED );
783853 goto on_done ;
784854 }
785855
786- if (aws_checksum_compute (allocator , algorithm , & body_cur , & checksum , 0 )) {
856+ if (aws_checksum_compute (allocator , algorithm , & body_cur , & checksum )) {
787857 AWS_LOGF_ERROR (
788858 AWS_LS_S3_META_REQUEST , "Failed to resume upload. Unable to compute checksum for the skipped part." );
789859 return_status = aws_raise_error (AWS_ERROR_S3_RESUME_FAILED );
0 commit comments