1 #ifndef AWS_S3_REQUEST_H
2 #define AWS_S3_REQUEST_H
3 
4 /**
5  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6  * SPDX-License-Identifier: Apache-2.0.
7  */
8 
9 #include <aws/common/byte_buf.h>
10 #include <aws/common/linked_list.h>
11 #include <aws/common/ref_count.h>
12 #include <aws/s3/s3.h>
13 
14 struct aws_http_message;
15 struct aws_signable;
16 struct aws_s3_meta_request;
17 
18 enum aws_s3_request_flags {
19     AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS = 0x00000001,
20     AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY = 0x00000002,
21     AWS_S3_REQUEST_FLAG_ALWAYS_SEND = 0x00000004,
22 };
23 
24 /* Represents a single request made to S3. */
25 struct aws_s3_request {
26 
27     /* Linked list node used for queuing. */
28     struct aws_linked_list_node node;
29 
30     /* TODO Ref count on the request is no longer needed--only one part of code should ever be holding onto a request,
31      * and we can just transfer ownership.*/
32     struct aws_ref_count ref_count;
33 
34     struct aws_allocator *allocator;
35 
36     /* Owning meta request. */
37     struct aws_s3_meta_request *meta_request;
38 
39     /* Request body to use when sending the request. The contents of this body will be re-used if a request is
40      * retried.*/
41     struct aws_byte_buf request_body;
42 
43     /* Beginning range of this part. */
44     /* TODO currently only used by auto_range_get, could be hooked up to auto_range_put as well. */
45     uint64_t part_range_start;
46 
47     /* Last byte of this part.*/
48     /* TODO currently only used by auto_range_get, could be hooked up to auto_range_put as well. */
49     uint64_t part_range_end;
50 
51     /* Part number that this request refers to.  If this is not a part, this can be 0.  (S3 Part Numbers start at 1.)
52      * However, must currently be a valid part number (ie: greater than 0) if the response body is to be streamed to the
53      * caller.
54      */
55     uint32_t part_number;
56 
57     /* Number of times aws_s3_meta_request_prepare has been called for a request. During the first call to the virtual
58      * prepare function, this will be 0.*/
59     uint32_t num_times_prepared;
60 
61     /* Tag that defines what the built request will actually consist of.  This is meant to be space for an enum defined
62      * by the derived type.  Request tags do not necessarily map 1:1 with actual S3 API requests.  For example, they can
63      * be more contextual, like "first part" instead of just "part".) */
64     int request_tag;
65 
66     /* Members of this structure will be repopulated each time the request is sent. If the request fails, and needs to
67      * be retried, then the members of this structure will be cleaned up and re-populated on the next send.
68      */
69     /* TODO rename this anonymous structure to something more intuitive. (Maybe "attempt_data")*/
70     struct {
71 
72         /* The HTTP message to send for this request. */
73         struct aws_http_message *message;
74 
75         /* Signable created for the above message. */
76         struct aws_signable *signable;
77 
78         /* Recorded response headers for the request. Set only when the request desc has record_response_headers set to
79          * true or when this response indicates an error. */
80         struct aws_http_headers *response_headers;
81 
82         /* Recorded response body of the request. */
83         struct aws_byte_buf response_body;
84 
85         /* Returned response status of this request. */
86         int response_status;
87 
88     } send_data;
89 
90     /* When true, response headers from the request will be stored in the request's response_headers variable. */
91     uint32_t record_response_headers : 1;
92 
93     /* When true, the response body buffer will be allocated in the size of a part. */
94     uint32_t part_size_response_body : 1;
95 
96     /* When true, this request is being tracked by the client for limiting the amount of in-flight-requests/stats. */
97     uint32_t tracked_by_client : 1;
98 
99     /* When true, even when the meta request has a finish result set, this request will be sent. */
100     uint32_t always_send : 1;
101 
102     /* When true, this request is intended to find out the object size. This is currently only used by auto_range_get.
103      */
104     uint32_t discovers_object_size : 1;
105 };
106 
107 AWS_EXTERN_C_BEGIN
108 
109 /* Create a new s3 request structure with the given options. */
110 AWS_S3_API
111 struct aws_s3_request *aws_s3_request_new(
112     struct aws_s3_meta_request *meta_request,
113     int request_tag,
114     uint32_t part_number,
115     uint32_t flags);
116 
117 /* Set up the request to be sent. Called each time before the request is sent. Will initially call
118  * aws_s3_request_clean_up_send_data to clear out anything previously existing in send_data. */
119 AWS_S3_API
120 void aws_s3_request_setup_send_data(struct aws_s3_request *request, struct aws_http_message *message);
121 
122 /* Clear out send_data members so that they can be repopulated before the next send. */
123 AWS_S3_API
124 void aws_s3_request_clean_up_send_data(struct aws_s3_request *request);
125 
126 AWS_S3_API
127 void aws_s3_request_acquire(struct aws_s3_request *request);
128 
129 AWS_S3_API
130 void aws_s3_request_release(struct aws_s3_request *request);
131 
132 AWS_EXTERN_C_END
133 
134 #endif
135