|
|
|
@ -624,25 +624,40 @@ static bool _tf_ssb_connection_get_request_callback(tf_ssb_connection_t* connect
|
|
|
|
|
|
|
|
|
|
void tf_ssb_connection_add_request(tf_ssb_connection_t* connection, int32_t request_number, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data, tf_ssb_connection_t* dependent_connection)
|
|
|
|
|
{
|
|
|
|
|
tf_ssb_connection_remove_request(connection, request_number);
|
|
|
|
|
tf_ssb_request_t request =
|
|
|
|
|
tf_ssb_request_t* existing = connection->requests_count ? bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare) : NULL;
|
|
|
|
|
if (existing)
|
|
|
|
|
{
|
|
|
|
|
.request_number = request_number,
|
|
|
|
|
.callback = callback,
|
|
|
|
|
.cleanup = cleanup,
|
|
|
|
|
.user_data = user_data,
|
|
|
|
|
.dependent_connection = dependent_connection,
|
|
|
|
|
};
|
|
|
|
|
int index = tf_util_insert_index(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare);
|
|
|
|
|
connection->requests = tf_resize_vec(connection->requests, sizeof(tf_ssb_request_t) * (connection->requests_count + 1));
|
|
|
|
|
if (connection->requests_count - index)
|
|
|
|
|
{
|
|
|
|
|
memmove(connection->requests + index + 1, connection->requests + index, sizeof(tf_ssb_request_t) * (connection->requests_count - index));
|
|
|
|
|
assert(!existing->callback);
|
|
|
|
|
assert(!existing->cleanup);
|
|
|
|
|
assert(!existing->user_data);
|
|
|
|
|
assert(!existing->dependent_connection);
|
|
|
|
|
existing->callback = callback;
|
|
|
|
|
existing->cleanup = cleanup;
|
|
|
|
|
existing->user_data = user_data;
|
|
|
|
|
existing->dependent_connection = dependent_connection;
|
|
|
|
|
}
|
|
|
|
|
connection->requests[index] = request;
|
|
|
|
|
connection->requests_count++;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tf_ssb_connection_remove_request(connection, request_number);
|
|
|
|
|
tf_ssb_request_t request =
|
|
|
|
|
{
|
|
|
|
|
.request_number = request_number,
|
|
|
|
|
.callback = callback,
|
|
|
|
|
.cleanup = cleanup,
|
|
|
|
|
.user_data = user_data,
|
|
|
|
|
.dependent_connection = dependent_connection,
|
|
|
|
|
};
|
|
|
|
|
int index = tf_util_insert_index(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare);
|
|
|
|
|
connection->requests = tf_resize_vec(connection->requests, sizeof(tf_ssb_request_t) * (connection->requests_count + 1));
|
|
|
|
|
if (connection->requests_count - index)
|
|
|
|
|
{
|
|
|
|
|
memmove(connection->requests + index + 1, connection->requests + index, sizeof(tf_ssb_request_t) * (connection->requests_count - index));
|
|
|
|
|
}
|
|
|
|
|
connection->requests[index] = request;
|
|
|
|
|
connection->requests_count++;
|
|
|
|
|
|
|
|
|
|
connection->ssb->request_count++;
|
|
|
|
|
connection->ssb->request_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int _message_request_compare(const void* a, const void* b)
|
|
|
|
@ -714,8 +729,19 @@ void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags,
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (flags & k_ssb_rpc_flag_new_request)
|
|
|
|
|
{
|
|
|
|
|
assert(request_number > 0);
|
|
|
|
|
assert(!_tf_ssb_connection_get_request_callback(connection, request_number, NULL, NULL));
|
|
|
|
|
}
|
|
|
|
|
else if (!_tf_ssb_connection_get_request_callback(connection, request_number, NULL, NULL))
|
|
|
|
|
{
|
|
|
|
|
tf_printf("Dropping message with no active request (%d): %.*s\n", request_number, (int)size, message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t* combined = tf_malloc(9 + size);
|
|
|
|
|
*combined = flags;
|
|
|
|
|
*combined = flags & k_ssb_rpc_mask_send;
|
|
|
|
|
uint32_t u32size = htonl((uint32_t)size);
|
|
|
|
|
memcpy(combined + 1, &u32size, sizeof(u32size));
|
|
|
|
|
uint32_t rn = htonl((uint32_t)request_number);
|
|
|
|
@ -723,20 +749,20 @@ void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags,
|
|
|
|
|
memcpy(combined + 1 + 2 * sizeof(uint32_t), message, size);
|
|
|
|
|
if (connection->ssb->verbose)
|
|
|
|
|
{
|
|
|
|
|
tf_printf(MAGENTA "%s RPC SEND" RESET " flags=%x RN=%d: [%zd B] %.*s\n", connection->name, flags, request_number, size, (flags & k_ssb_rpc_mask_type) == k_ssb_rpc_flag_binary ? 0 : (int)size, message);
|
|
|
|
|
tf_printf(MAGENTA "%s RPC SEND" RESET " flags=%x RN=%d: [%zd B] %.*s\n", connection->name, flags & k_ssb_rpc_mask_send, request_number, size, (flags & k_ssb_rpc_mask_type) == k_ssb_rpc_flag_binary ? 0 : (int)size, message);
|
|
|
|
|
}
|
|
|
|
|
_tf_ssb_connection_add_debug_message(connection, true, flags, request_number, message, size);
|
|
|
|
|
_tf_ssb_connection_add_debug_message(connection, true, flags & k_ssb_rpc_mask_send, request_number, message, size);
|
|
|
|
|
_tf_ssb_connection_box_stream_send(connection, combined, 1 + 2 * sizeof(uint32_t) + size);
|
|
|
|
|
tf_free(combined);
|
|
|
|
|
connection->ssb->rpc_out++;
|
|
|
|
|
if (request_number > 0 && callback)
|
|
|
|
|
if (flags & k_ssb_rpc_flag_end_error)
|
|
|
|
|
{
|
|
|
|
|
tf_ssb_connection_remove_request(connection, request_number);
|
|
|
|
|
}
|
|
|
|
|
else if (flags & k_ssb_rpc_flag_new_request)
|
|
|
|
|
{
|
|
|
|
|
tf_ssb_connection_add_request(connection, request_number, callback, cleanup, user_data, NULL);
|
|
|
|
|
}
|
|
|
|
|
else if (cleanup)
|
|
|
|
|
{
|
|
|
|
|
cleanup(connection->ssb, user_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tf_ssb_connection_rpc_send_json(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue message, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data)
|
|
|
|
@ -747,7 +773,7 @@ void tf_ssb_connection_rpc_send_json(tf_ssb_connection_t* connection, uint8_t fl
|
|
|
|
|
const char* json_string = JS_ToCStringLen(context, &size, json);
|
|
|
|
|
tf_ssb_connection_rpc_send(
|
|
|
|
|
connection,
|
|
|
|
|
k_ssb_rpc_flag_json | (flags & k_ssb_rpc_flag_stream) | (flags & k_ssb_rpc_flag_end_error),
|
|
|
|
|
k_ssb_rpc_flag_json | (flags & ~k_ssb_rpc_mask_type),
|
|
|
|
|
request_number,
|
|
|
|
|
(const uint8_t*)json_string,
|
|
|
|
|
size,
|
|
|
|
@ -1474,6 +1500,7 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
|
|
|
|
|
{
|
|
|
|
|
connection->ssb->rpc_in++;
|
|
|
|
|
_tf_ssb_connection_add_debug_message(connection, false, flags, request_number, message, size);
|
|
|
|
|
bool close_connection = false;
|
|
|
|
|
if (size == 0)
|
|
|
|
|
{
|
|
|
|
|
_tf_ssb_connection_close(connection, "rpc recv zero");
|
|
|
|
@ -1492,9 +1519,25 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
|
|
|
|
|
|
|
|
|
|
if (!JS_IsUndefined(val))
|
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
if (JS_IsObject(val))
|
|
|
|
|
tf_ssb_rpc_callback_t* callback = NULL;
|
|
|
|
|
void* user_data = NULL;
|
|
|
|
|
if (_tf_ssb_connection_get_request_callback(connection, -request_number, &callback, &user_data))
|
|
|
|
|
{
|
|
|
|
|
if (callback)
|
|
|
|
|
{
|
|
|
|
|
char buffer[64];
|
|
|
|
|
snprintf(buffer, sizeof(buffer), "request %d", request_number);
|
|
|
|
|
tf_trace_begin(connection->ssb->trace, buffer);
|
|
|
|
|
PRE_CALLBACK(connection->ssb, callback);
|
|
|
|
|
callback(connection, flags, request_number, val, message, size, user_data);
|
|
|
|
|
POST_CALLBACK(connection->ssb, callback);
|
|
|
|
|
tf_trace_end(connection->ssb->trace);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (JS_IsObject(val))
|
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
tf_ssb_connection_add_request(connection, -request_number, NULL, NULL, NULL, NULL);
|
|
|
|
|
for (tf_ssb_rpc_callback_node_t* it = connection->ssb->rpc; it; it = it->next)
|
|
|
|
|
{
|
|
|
|
|
if (_tf_ssb_name_equals(context, val, it->name))
|
|
|
|
@ -1508,35 +1551,19 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found)
|
|
|
|
|
{
|
|
|
|
|
tf_ssb_rpc_callback_t* callback = NULL;
|
|
|
|
|
void* user_data = NULL;
|
|
|
|
|
if (_tf_ssb_connection_get_request_callback(connection, -request_number, &callback, &user_data))
|
|
|
|
|
{
|
|
|
|
|
if (callback)
|
|
|
|
|
{
|
|
|
|
|
char buffer[64];
|
|
|
|
|
snprintf(buffer, sizeof(buffer), "request %d", request_number);
|
|
|
|
|
tf_trace_begin(connection->ssb->trace, buffer);
|
|
|
|
|
PRE_CALLBACK(connection->ssb, callback);
|
|
|
|
|
callback(connection, flags, request_number, val, message, size, user_data);
|
|
|
|
|
POST_CALLBACK(connection->ssb, callback);
|
|
|
|
|
tf_trace_end(connection->ssb->trace);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (!_tf_ssb_name_equals(context, val, (const char*[]) { "Error", NULL }))
|
|
|
|
|
if (!found)
|
|
|
|
|
{
|
|
|
|
|
char buffer[256];
|
|
|
|
|
_tf_ssb_name_to_string(context, val, buffer, sizeof(buffer));
|
|
|
|
|
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tf_printf("Failed to parse %.*s\n", (int)size, message);
|
|
|
|
|
close_connection = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS_FreeValue(context, val);
|
|
|
|
@ -1568,9 +1595,9 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags & k_ssb_rpc_flag_end_error)
|
|
|
|
|
if (close_connection)
|
|
|
|
|
{
|
|
|
|
|
tf_ssb_connection_remove_request(connection, -request_number);
|
|
|
|
|
tf_ssb_connection_close(connection);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|