in source/mqtt_client_connection.c [360:454]
static void s_ws_handshake_transform(
struct aws_http_message *request,
void *user_data,
aws_mqtt_transform_websocket_handshake_complete_fn *complete_fn,
void *complete_ctx) {
struct mqtt_connection_binding *connection_binding = user_data;
bool success = false;
/* We'll create a ws_handshake_transform_data object, place it in a capsule, and pass it to callback */
struct ws_handshake_transform_data *ws_transform_data = NULL;
PyObject *ws_transform_capsule = NULL;
/*************** GIL ACQUIRE ***************
* If error occurs, ensure an aws error is raised and goto done */
PyGILState_STATE state;
if (aws_py_gilstate_ensure(&state)) {
return; /* Python has shut down. Nothing matters anymore, but don't crash */
}
/* Ensure python mqtt connection object is still alive */
PyObject *connection_py = PyWeakref_GetObject(connection_binding->self_proxy); /* borrowed reference */
if (connection_py == Py_None) {
aws_raise_error(AWS_ERROR_INVALID_STATE);
goto done;
}
ws_transform_data = aws_mem_calloc(aws_py_get_allocator(), 1, sizeof(struct ws_handshake_transform_data));
if (!ws_transform_data) {
goto done;
}
ws_transform_capsule = PyCapsule_New(
ws_transform_data, s_capsule_name_ws_handshake_transform_data, s_ws_handshake_transform_data_destructor);
if (!ws_transform_capsule) {
aws_py_raise_error();
goto done;
}
/* From hereon, capsule destructor will clean up anything stored within it */
ws_transform_data->request = request;
ws_transform_data->complete_fn = complete_fn;
ws_transform_data->complete_ctx = complete_ctx;
ws_transform_data->connection_py = connection_py;
Py_INCREF(ws_transform_data->connection_py);
ws_transform_data->request_binding_py = aws_py_http_message_new_request_from_native(request);
if (!ws_transform_data->request_binding_py) {
aws_py_raise_error();
goto done;
}
ws_transform_data->headers_binding_py = aws_py_http_headers_new_from_native(aws_http_message_get_headers(request));
if (!ws_transform_data->headers_binding_py) {
aws_py_raise_error();
goto done;
}
PyObject *result = PyObject_CallMethod(
connection_py,
"_ws_handshake_transform",
"(OOO)",
ws_transform_data->request_binding_py,
ws_transform_data->headers_binding_py,
ws_transform_capsule);
if (result) {
Py_DECREF(result);
} else {
aws_py_raise_error();
goto done;
}
success = true;
done:;
/* Save off error code, so it doesn't got stomped before we pass it to callback*/
int error_code = aws_last_error();
if (ws_transform_capsule) {
Py_DECREF(ws_transform_capsule);
} else if (ws_transform_data) {
aws_mem_release(aws_py_get_allocator(), ws_transform_data);
}
PyGILState_Release(state);
/*************** GIL RELEASE ***************/
/* Invoke completion cb if we failed to pass data to user. */
if (!success) {
complete_fn(request, error_code, complete_ctx);
}
}