diff --git a/awscrt/s3.py b/awscrt/s3.py index 816a718ae..6676fcb3d 100644 --- a/awscrt/s3.py +++ b/awscrt/s3.py @@ -302,7 +302,8 @@ def make_request( on_headers=None, on_body=None, on_done=None, - on_progress=None): + on_progress=None, + network_interface_names=None): """Create the Request to the the S3 server, :attr:`~S3RequestType.GET_OBJECT`/:attr:`~S3RequestType.PUT_OBJECT` requests are split it into multi-part requests under the hood for acceleration. @@ -449,6 +450,8 @@ def make_request( * `**kwargs` (dict): Forward-compatibility kwargs. + network_interface_names: (Optional[list(str)]) + Returns: S3Request """ @@ -468,7 +471,8 @@ def make_request( on_body=on_body, on_done=on_done, on_progress=on_progress, - region=self._region) + region=self._region, + network_interface_names=network_interface_names) class S3Request(NativeResource): @@ -505,7 +509,8 @@ def __init__( on_body=None, on_done=None, on_progress=None, - region=None): + region=None, + network_interface_names=None): assert isinstance(client, S3Client) assert isinstance(request, HttpRequest) assert callable(on_headers) or on_headers is None @@ -513,6 +518,7 @@ def __init__( assert callable(on_done) or on_done is None assert isinstance(part_size, int) or part_size is None assert isinstance(multipart_upload_threshold, int) or multipart_upload_threshold is None + assert isinstance(network_interface_names, list) and all(isinstance(name, str) for name in network_interface_names) or network_interface_names is None if type == S3RequestType.DEFAULT and not operation_name: raise ValueError("'operation_name' must be set when using S3RequestType.DEFAULT") @@ -564,7 +570,8 @@ def __init__( validate_response_checksum, part_size, multipart_upload_threshold, - s3_request_core) + s3_request_core, + network_interface_names) @property def finished_future(self): diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c index 7586537e5..c4c68b542 100644 --- a/source/s3_meta_request.c +++ b/source/s3_meta_request.c @@ -377,9 +377,11 @@ PyObject *aws_py_s3_client_make_meta_request(PyObject *self, PyObject *args) { uint64_t part_size; /* K */ uint64_t multipart_upload_threshold; /* K */ PyObject *py_core; /* O */ + PyObject *network_interface_names_py; /* O */ + if (!PyArg_ParseTuple( args, - "OOOizOOzzs#iipKKO", + "OOOizOOzzs#iipKKOO", &py_s3_request, &s3_client_py, &http_request_py, @@ -396,7 +398,8 @@ PyObject *aws_py_s3_client_make_meta_request(PyObject *self, PyObject *args) { &validate_response_checksum, &part_size, &multipart_upload_threshold, - &py_core)) { + &py_core, + &network_interface_names_py)) { return NULL; } struct aws_s3_client *s3_client = aws_py_get_s3_client(s3_client_py); @@ -438,6 +441,19 @@ PyObject *aws_py_s3_client_make_meta_request(PyObject *self, PyObject *args) { .validate_response_checksum = validate_response_checksum != 0, }; + struct aws_byte_cursor *network_interface_names = NULL; + int num_network_interface_names = 0; + + if (network_interface_names_py != Py_None) { + if (!PyList_Check(network_interface_names_py)) { + // waahm7: todo, correct way to raise errors? + PyErr_SetString(PyExc_TypeError, "Expected a list"); + return NULL; + } + Py_ssize_t listSize = PyList_Size(listObj); + num_network_interface_names = (size_t)listSize; + } + struct s3_meta_request_binding *meta_request = aws_mem_calloc(allocator, 1, sizeof(struct s3_meta_request_binding)); if (!meta_request) { return PyErr_AwsLastError(); @@ -464,6 +480,15 @@ PyObject *aws_py_s3_client_make_meta_request(PyObject *self, PyObject *args) { } } + if (num_network_interface_names > 0) { + network_interface_names = + aws_mem_calloc(allocator, num_network_interface_names, sizeof(struct aws_byte_cursor)); + for (Py_ssize_t i = 0; i < listSize; ++i) { + PyObject *strObj = PyList_GetItem(listObj, i); + network_interface_names[i] = aws_byte_cursor_from_pyunicode(strObj); + } + } + struct aws_s3_meta_request_options s3_meta_request_opt = { .type = type, .operation_name = aws_byte_cursor_from_c_str(operation_name), @@ -479,12 +504,15 @@ PyObject *aws_py_s3_client_make_meta_request(PyObject *self, PyObject *args) { .part_size = part_size, .multipart_upload_threshold = multipart_upload_threshold, .user_data = meta_request, + .network_interface_names = network_interface_names, + .num_network_interface_names = num_network_interface_names, }; if (aws_high_res_clock_get_ticks(&meta_request->last_sampled_time)) { goto error; } meta_request->native = aws_s3_client_make_meta_request(s3_client, &s3_meta_request_opt); + aws_mem_cleanup(allocator, network_interface_names); if (meta_request->native == NULL) { PyErr_SetAwsLastError(); goto error;