Add missing .clang-format, and fix some spaces that slipped through.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4856 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2024-02-17 19:22:02 +00:00
parent 1958623a7a
commit d0e11bc68b
23 changed files with 583 additions and 597 deletions

20
.clang-format Normal file
View File

@ -0,0 +1,20 @@
# Format Style Options - Created with Clang Power Tools
---
BasedOnStyle: WebKit
AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
ColumnLimit: 180
ContinuationIndentWidth: 4
IndentCaseBlocks: true
IndentWidth: 4
MaxEmptyLinesToKeep: 1
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: false
SortIncludes: false
TabWidth: 4
UseTab: Always
...

View File

@ -105,7 +105,7 @@ static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc
size_t length; size_t length;
const char* keyString = JS_ToCStringLen(context, &length, argv[0]); const char* keyString = JS_ToCStringLen(context, &length, argv[0]);
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, keyString, length, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, keyString, length, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW) sqlite3_step(statement) == SQLITE_ROW)
{ {
entry = JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0)); entry = JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0));
} }
@ -132,7 +132,7 @@ static JSValue _database_set(JSContext* context, JSValueConst this_val, int argc
size_t valueLength; size_t valueLength;
const char* valueString = JS_ToCStringLen(context, &valueLength, argv[1]); const char* valueString = JS_ToCStringLen(context, &valueLength, argv[1]);
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, keyString, keyLength, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, keyString, keyLength, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, valueString, valueLength, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_OK) sqlite3_bind_text(statement, 3, valueString, valueLength, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_OK)
{ {
} }
JS_FreeCString(context, keyString); JS_FreeCString(context, keyString);
@ -162,7 +162,7 @@ static JSValue _database_exchange(JSContext* context, JSValueConst this_val, int
const char* key = JS_ToCStringLen(context, &key_length, argv[0]); const char* key = JS_ToCStringLen(context, &key_length, argv[0]);
const char* set = JS_ToCStringLen(context, &set_length, argv[2]); const char* set = JS_ToCStringLen(context, &set_length, argv[2]);
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, key, key_length, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, key, key_length, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, set, set_length, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE) sqlite3_bind_text(statement, 3, set, set_length, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE)
{ {
exchanged = sqlite3_changes(db) != 0 ? JS_TRUE : JS_FALSE; exchanged = sqlite3_changes(db) != 0 ? JS_TRUE : JS_FALSE;
} }
@ -180,8 +180,8 @@ static JSValue _database_exchange(JSContext* context, JSValueConst this_val, int
const char* expected = JS_ToCStringLen(context, &expected_length, argv[1]); const char* expected = JS_ToCStringLen(context, &expected_length, argv[1]);
const char* set = JS_ToCStringLen(context, &set_length, argv[2]); const char* set = JS_ToCStringLen(context, &set_length, argv[2]);
if (sqlite3_bind_text(statement, 1, set, set_length, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, database->id, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, set, set_length, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, database->id, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, key, key_length, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 4, expected, expected_length, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 3, key, key_length, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 4, expected, expected_length, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_DONE) sqlite3_step(statement) == SQLITE_DONE)
{ {
exchanged = sqlite3_changes(db) != 0 ? JS_TRUE : JS_FALSE; exchanged = sqlite3_changes(db) != 0 ? JS_TRUE : JS_FALSE;
} }
@ -208,7 +208,7 @@ static JSValue _database_remove(JSContext* context, JSValueConst this_val, int a
size_t keyLength; size_t keyLength;
const char* keyString = JS_ToCStringLen(context, &keyLength, argv[0]); const char* keyString = JS_ToCStringLen(context, &keyLength, argv[0]);
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, keyString, keyLength, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, keyString, keyLength, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_OK) sqlite3_step(statement) == SQLITE_OK)
{ {
} }
JS_FreeCString(context, keyString); JS_FreeCString(context, keyString);
@ -236,8 +236,7 @@ static JSValue _database_get_all(JSContext* context, JSValueConst this_val, int
uint32_t index = 0; uint32_t index = 0;
while (sqlite3_step(statement) == SQLITE_ROW) while (sqlite3_step(statement) == SQLITE_ROW)
{ {
JS_SetPropertyUint32( JS_SetPropertyUint32(context, array, index++, JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0)));
context, array, index++, JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0)));
} }
} }
sqlite3_finalize(statement); sqlite3_finalize(statement);
@ -265,7 +264,7 @@ static JSValue _database_get_like(JSContext* context, JSValueConst this_val, int
while (sqlite3_step(statement) == SQLITE_ROW) while (sqlite3_step(statement) == SQLITE_ROW)
{ {
JS_SetPropertyStr(context, result, (const char*)sqlite3_column_text(statement, 0), JS_SetPropertyStr(context, result, (const char*)sqlite3_column_text(statement, 0),
JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 1), sqlite3_column_bytes(statement, 1))); JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 1), sqlite3_column_bytes(statement, 1)));
} }
} }
JS_FreeCString(context, pattern); JS_FreeCString(context, pattern);
@ -292,8 +291,7 @@ static JSValue _databases_list(JSContext* context, JSValueConst this_val, int ar
uint32_t index = 0; uint32_t index = 0;
while (sqlite3_step(statement) == SQLITE_ROW) while (sqlite3_step(statement) == SQLITE_ROW)
{ {
JS_SetPropertyUint32( JS_SetPropertyUint32(context, array, index++, JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0)));
context, array, index++, JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0)));
} }
} }
JS_FreeCString(context, pattern); JS_FreeCString(context, pattern);

View File

@ -132,8 +132,7 @@ static bool _http_find_handler(tf_http_t* http, const char* path, tf_http_callba
for (int i = 0; i < http->handlers_count; i++) for (int i = 0; i < http->handlers_count; i++)
{ {
if (!http->handlers[i].pattern || !*http->handlers[i].pattern || strcmp(path, http->handlers[i].pattern) == 0 || if (!http->handlers[i].pattern || !*http->handlers[i].pattern || strcmp(path, http->handlers[i].pattern) == 0 ||
(*http->handlers[i].pattern && strncmp(path, http->handlers[i].pattern, strlen(http->handlers[i].pattern)) == 0 && (*http->handlers[i].pattern && strncmp(path, http->handlers[i].pattern, strlen(http->handlers[i].pattern)) == 0 && path[strlen(http->handlers[i].pattern) - 1] == '/'))
path[strlen(http->handlers[i].pattern) - 1] == '/'))
{ {
*out_callback = http->handlers[i].callback; *out_callback = http->handlers[i].callback;
*out_trace_name = http->handlers[i].pattern; *out_trace_name = http->handlers[i].pattern;
@ -301,8 +300,7 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d
size_t total_length = mask_start + 4 + length; size_t total_length = mask_start + 4 + length;
if (connection->body_length >= total_length) if (connection->body_length >= total_length)
{ {
uint32_t mask = uint32_t mask = (uint32_t)p[mask_start + 0] | (uint32_t)p[mask_start + 1] << 8 | (uint32_t)p[mask_start + 2] << 16 | (uint32_t)p[mask_start + 3] << 24;
(uint32_t)p[mask_start + 0] | (uint32_t)p[mask_start + 1] << 8 | (uint32_t)p[mask_start + 2] << 16 | (uint32_t)p[mask_start + 3] << 24;
uint8_t* message = p + mask_start + 4; uint8_t* message = p + mask_start + 4;
_http_websocket_mask_in_place(message, mask, length); _http_websocket_mask_in_place(message, mask, length);
@ -324,8 +322,7 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d
{ {
tf_trace_begin(connection->http->trace, connection->trace_name ? connection->trace_name : "websocket"); tf_trace_begin(connection->http->trace, connection->trace_name ? connection->trace_name : "websocket");
connection->request->on_message(connection->request, connection->fragment_length ? connection->fragment_op_code : op_code, connection->request->on_message(connection->request, connection->fragment_length ? connection->fragment_op_code : op_code,
connection->fragment_length ? connection->fragment : message, connection->fragment_length ? connection->fragment : message, connection->fragment_length ? connection->fragment_length : length);
connection->fragment_length ? connection->fragment_length : length);
tf_trace_end(connection->http->trace); tf_trace_end(connection->http->trace);
} }
connection->fragment_length = 0; connection->fragment_length = 0;
@ -397,7 +394,7 @@ static size_t _http_on_read_plain_internal(tf_http_connection_t* connection, con
size_t header_count = sizeof(connection->headers) / sizeof(*connection->headers); size_t header_count = sizeof(connection->headers) / sizeof(*connection->headers);
int parse_result = phr_parse_request(connection->headers_buffer, connection->headers_buffer_length, &method, &method_length, &path, &path_length, int parse_result = phr_parse_request(connection->headers_buffer, connection->headers_buffer_length, &method, &method_length, &path, &path_length,
&connection->minor_version, connection->headers, &header_count, connection->parsed_length); &connection->minor_version, connection->headers, &header_count, connection->parsed_length);
connection->parsed_length = connection->headers_buffer_length; connection->parsed_length = connection->headers_buffer_length;
if (parse_result > 0) if (parse_result > 0)
{ {
@ -445,8 +442,7 @@ static size_t _http_on_read_plain_internal(tf_http_connection_t* connection, con
connection->body = tf_realloc(connection->body, connection->content_length); connection->body = tf_realloc(connection->body, connection->content_length);
} }
if (!_http_find_handler(connection->http, connection->path, &connection->callback, &connection->trace_name, &connection->user_data) || if (!_http_find_handler(connection->http, connection->path, &connection->callback, &connection->trace_name, &connection->user_data) || !connection->callback)
!connection->callback)
{ {
connection->callback = _http_builtin_404_handler; connection->callback = _http_builtin_404_handler;
connection->trace_name = "404"; connection->trace_name = "404";

View File

@ -305,8 +305,7 @@ static JSValue _httpd_websocket_upgrade(JSContext* context, JSValueConst this_va
headers[headers_count * 2 + 1] = key; headers[headers_count * 2 + 1] = key;
headers_count++; headers_count++;
bool send_version = bool send_version = !tf_http_request_get_header(request, "sec-websocket-version") || strcmp(tf_http_request_get_header(request, "sec-websocket-version"), "13") != 0;
!tf_http_request_get_header(request, "sec-websocket-version") || strcmp(tf_http_request_get_header(request, "sec-websocket-version"), "13") != 0;
if (send_version) if (send_version)
{ {
headers[headers_count * 2 + 0] = "Sec-WebSocket-Accept"; headers[headers_count * 2 + 0] = "Sec-WebSocket-Accept";
@ -697,8 +696,8 @@ static void _httpd_endpoint_robots_txt(tf_http_request_t* request)
return; return;
} }
char* response = "User-Agent: *\n" char* response = "User-Agent: *\n"
"Disallow: /*/*/edit\n" "Disallow: /*/*/edit\n"
"Allow: /\n"; "Allow: /\n";
const char* headers[] = { "Content-Type", "text/plain; charset=utf-8" }; const char* headers[] = { "Content-Type", "text/plain; charset=utf-8" };
tf_http_respond(request, 200, headers, tf_countof(headers) / 2, response, response ? strlen(response) : 0); tf_http_respond(request, 200, headers, tf_countof(headers) / 2, response, response ? strlen(response) : 0);
} }

View File

@ -46,9 +46,9 @@ static void _start_initial_load(WKWebView* web_view)
} }
- (void)webView:(WKWebView*)webView - (void)webView:(WKWebView*)webView
runJavaScriptConfirmPanelWithMessage:(NSString*)message runJavaScriptConfirmPanelWithMessage:(NSString*)message
initiatedByFrame:(WKFrameInfo*)frame initiatedByFrame:(WKFrameInfo*)frame
completionHandler:(void (^)(BOOL result))completionHandler completionHandler:(void (^)(BOOL result))completionHandler
{ {
UIAlertController* alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert]; UIAlertController* alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action) { completionHandler(true); }]]; [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action) { completionHandler(true); }]];
@ -63,26 +63,23 @@ static void _start_initial_load(WKWebView* web_view)
[self presentViewController:alertController animated:YES completion:^ {}]; [self presentViewController:alertController animated:YES completion:^ {}];
} }
- (void)webView:(WKWebView*)webView - (void)webView:(WKWebView*)webView
runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt
defaultText:(NSString*)defaultText defaultText:(NSString*)defaultText
initiatedByFrame:(WKFrameInfo*)frame initiatedByFrame:(WKFrameInfo*)frame
completionHandler:(void (^)(NSString*))completionHandler completionHandler:(void (^)(NSString*))completionHandler
{ {
NSString* sender = [NSString stringWithFormat:@"%@", self.web_view.URL.host]; NSString* sender = [NSString stringWithFormat:@"%@", self.web_view.URL.host];
UIAlertController* alertController = [UIAlertController alertControllerWithTitle:prompt message:sender preferredStyle:UIAlertControllerStyleAlert]; UIAlertController* alertController = [UIAlertController alertControllerWithTitle:prompt message:sender preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField* textField) { [alertController addTextFieldWithConfigurationHandler:^(UITextField* textField) {
textField.placeholder = defaultText; textField.placeholder = defaultText;
textField.text = defaultText; textField.text = defaultText;
}]; }];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action) {
style:UIAlertActionStyleDefault NSString* input = ((UITextField*)alertController.textFields.firstObject).text;
handler:^(UIAlertAction* action) { completionHandler(input);
NSString* input = ((UITextField*)alertController.textFields.firstObject).text; }]];
completionHandler(input);
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction* action) { completionHandler(nil); }]]; [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction* action) { completionHandler(nil); }]];
[self presentViewController:alertController animated:YES completion:^ {}]; [self presentViewController:alertController animated:YES completion:^ {}];
} }

View File

@ -42,7 +42,7 @@ struct backtrace_state* g_backtrace_state;
const char* k_db_path_default = "db.sqlite"; const char* k_db_path_default = "db.sqlite";
#define XOPT_PARSE( \ #define XOPT_PARSE( \
name, flags, options, config_ptr, argc, argv, extrac_ptr, extrav_ptr, err_ptr, autohelp_file, autohelp_usage, autohelp_prefix, autohelp_suffix, autohelp_spacer) \ name, flags, options, config_ptr, argc, argv, extrac_ptr, extrav_ptr, err_ptr, autohelp_file, autohelp_usage, autohelp_prefix, autohelp_suffix, autohelp_spacer) \
do \ do \
{ \ { \
xoptContext* _xopt_ctx; \ xoptContext* _xopt_ctx; \
@ -117,8 +117,7 @@ static int _tf_command_test(const char* file, int argc, char* argv[])
const char** extras = NULL; const char** extras = NULL;
int extra_count = 0; int extra_count = 0;
const char* err = NULL; const char* err = NULL;
XOPT_PARSE( XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "test [options]", "options:", NULL, 15);
file, XOPT_CTX_KEEPFIRST | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "test [options]", "options:", NULL, 15);
if (err) if (err)
{ {
fprintf(stderr, "Error: %s\n", err); fprintf(stderr, "Error: %s\n", err);
@ -165,7 +164,7 @@ static int _tf_command_import(const char* file, int argc, char* argv[])
int extra_count = 0; int extra_count = 0;
const char* err = NULL; const char* err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr,
"import [options] [paths] ...", "options:", NULL, 15); "import [options] [paths] ...", "options:", NULL, 15);
if (err) if (err)
{ {
fprintf(stderr, "Error: %s\n", err); fprintf(stderr, "Error: %s\n", err);
@ -223,7 +222,7 @@ static int _tf_command_export(const char* file, int argc, char* argv[])
int extra_count = 0; int extra_count = 0;
const char* err = NULL; const char* err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr,
"export [options] [paths] ...", "options:", NULL, 15); "export [options] [paths] ...", "options:", NULL, 15);
if (err) if (err)
{ {
fprintf(stderr, "Error: %s\n", err); fprintf(stderr, "Error: %s\n", err);
@ -440,7 +439,7 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
int extra_count = 0; int extra_count = 0;
const char* err = NULL; const char* err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr,
"run [options] [paths] ...", "options:", NULL, 15); "run [options] [paths] ...", "options:", NULL, 15);
if (err) if (err)
{ {
@ -513,7 +512,7 @@ static int _tf_command_sandbox(const char* file, int argc, char* argv[])
int extra_count = 0; int extra_count = 0;
const char* err = NULL; const char* err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr,
"sandbox [options]", "options:", NULL, 15); "sandbox [options]", "options:", NULL, 15);
if (err) if (err)
{ {
fprintf(stderr, "Error: %s\n", err); fprintf(stderr, "Error: %s\n", err);
@ -614,9 +613,9 @@ static void _startup(int argc, char* argv[])
{ {
if ( if (
#if !defined(_WIN32) #if !defined(_WIN32)
signal(SIGSYS, _error_handler) == SIG_ERR || signal(SIGSYS, _error_handler) == SIG_ERR ||
#endif #endif
signal(SIGSEGV, _error_handler) == SIG_ERR) signal(SIGSEGV, _error_handler) == SIG_ERR)
{ {
perror("signal"); perror("signal");
} }

View File

@ -166,7 +166,7 @@ static void _tf_mem_summarize(void* ptr, size_t size, int frames_count, void* co
int index = tf_util_insert_index(&allocation, summary->allocations, summary->count, sizeof(tf_mem_allocation_t), _tf_mem_hash_stack_compare); int index = tf_util_insert_index(&allocation, summary->allocations, summary->count, sizeof(tf_mem_allocation_t), _tf_mem_hash_stack_compare);
if (index < summary->count && allocation.stack_hash == summary->allocations[index].stack_hash && allocation.frames_count == summary->allocations[index].frames_count && if (index < summary->count && allocation.stack_hash == summary->allocations[index].stack_hash && allocation.frames_count == summary->allocations[index].frames_count &&
memcmp(frames, summary->allocations[index].frames, sizeof(void*) * frames_count) == 0) memcmp(frames, summary->allocations[index].frames, sizeof(void*) * frames_count) == 0)
{ {
summary->allocations[index].count++; summary->allocations[index].count++;
summary->allocations[index].size += size; summary->allocations[index].size += size;

View File

@ -451,16 +451,14 @@ static void _socket_onResolvedForBind(uv_getaddrinfo_t* resolver, int status, st
socket_resolve_data_t* data = (socket_resolve_data_t*)resolver->data; socket_resolve_data_t* data = (socket_resolve_data_t*)resolver->data;
if (status != 0) if (status != 0)
{ {
tf_task_reject_promise( tf_task_reject_promise(data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), "uv_getaddrinfo: %s", uv_strerror(status)));
data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), "uv_getaddrinfo: %s", uv_strerror(status)));
} }
else else
{ {
int bindResult = uv_tcp_bind(&data->socket->_socket, result->ai_addr, 0); int bindResult = uv_tcp_bind(&data->socket->_socket, result->ai_addr, 0);
if (bindResult != 0) if (bindResult != 0)
{ {
tf_task_reject_promise( tf_task_reject_promise(data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), "uv_tcp_bind: %s", uv_strerror(bindResult)));
data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), "uv_tcp_bind: %s", uv_strerror(bindResult)));
} }
else else
{ {

View File

@ -482,8 +482,7 @@ static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t si
} }
else if (connection->tunnel_connection) else if (connection->tunnel_connection)
{ {
tf_ssb_connection_rpc_send( tf_ssb_connection_rpc_send(connection->tunnel_connection, k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream, -connection->tunnel_request_number, data, size, NULL, NULL, NULL);
connection->tunnel_connection, k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream, -connection->tunnel_request_number, data, size, NULL, NULL, NULL);
} }
} }
@ -556,7 +555,6 @@ static void _tf_ssb_connection_send_identity(tf_ssb_connection_t* connection, ui
connection->state = k_tf_ssb_state_sent_identity; connection->state = k_tf_ssb_state_sent_identity;
} }
static void _tf_ssb_nonce_inc(uint8_t* nonce) static void _tf_ssb_nonce_inc(uint8_t* nonce)
{ {
int i = 23; int i = 23;
@ -643,10 +641,10 @@ 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, 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_t* dependent_connection)
{ {
tf_ssb_request_t* existing = tf_ssb_request_t* existing =
connection->requests_count ? bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare) : NULL; connection->requests_count ? bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare) : NULL;
if (existing) if (existing)
{ {
assert(!existing->callback); assert(!existing->callback);
@ -691,7 +689,7 @@ static int _message_request_compare(const void* a, const void* b)
void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection, const char* author, int32_t request_number, bool keys) void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection, const char* author, int32_t request_number, bool keys)
{ {
int index = int index =
tf_util_insert_index(author, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare); tf_util_insert_index(author, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare);
if (index < connection->message_requests_count && strcmp(author, connection->message_requests[index].author) == 0) if (index < connection->message_requests_count && strcmp(author, connection->message_requests[index].author) == 0)
{ {
connection->message_requests[index].request_number = request_number; connection->message_requests[index].request_number = request_number;
@ -702,7 +700,7 @@ void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection,
if (connection->message_requests_count - index) if (connection->message_requests_count - index)
{ {
memmove(connection->message_requests + index + 1, connection->message_requests + index, memmove(connection->message_requests + index + 1, connection->message_requests + index,
sizeof(tf_ssb_connection_message_request_t) * (connection->message_requests_count - index)); sizeof(tf_ssb_connection_message_request_t) * (connection->message_requests_count - index));
} }
connection->message_requests[index] = (tf_ssb_connection_message_request_t) { connection->message_requests[index] = (tf_ssb_connection_message_request_t) {
.request_number = request_number, .request_number = request_number,
@ -715,11 +713,11 @@ void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection,
void tf_ssb_connection_remove_new_message_request(tf_ssb_connection_t* connection, const char* author) void tf_ssb_connection_remove_new_message_request(tf_ssb_connection_t* connection, const char* author)
{ {
int index = int index =
tf_util_insert_index(author, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare); tf_util_insert_index(author, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare);
if (index < connection->message_requests_count && strcmp(author, connection->message_requests[index].author) == 0) if (index < connection->message_requests_count && strcmp(author, connection->message_requests[index].author) == 0)
{ {
memmove(connection->message_requests + index, connection->message_requests + index + 1, memmove(connection->message_requests + index, connection->message_requests + index + 1,
sizeof(tf_ssb_connection_message_request_t) * (connection->message_requests_count - index - 1)); sizeof(tf_ssb_connection_message_request_t) * (connection->message_requests_count - index - 1));
connection->message_requests_count--; connection->message_requests_count--;
} }
} }
@ -727,7 +725,7 @@ void tf_ssb_connection_remove_new_message_request(tf_ssb_connection_t* connectio
void tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t request_number) void tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t request_number)
{ {
tf_ssb_request_t* request = tf_ssb_request_t* request =
connection->requests_count ? bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare) : NULL; connection->requests_count ? bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare) : NULL;
if (request) if (request)
{ {
if (request->cleanup) if (request->cleanup)
@ -743,7 +741,7 @@ void tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t r
} }
void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const uint8_t* message, size_t size, tf_ssb_rpc_callback_t* callback, void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const uint8_t* message, size_t size, tf_ssb_rpc_callback_t* callback,
tf_ssb_callback_cleanup_t* cleanup, void* user_data) tf_ssb_callback_cleanup_t* cleanup, void* user_data)
{ {
if (!connection) if (!connection)
{ {
@ -773,9 +771,9 @@ void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags,
memcpy(combined + 1 + 2 * sizeof(uint32_t), message, size); memcpy(combined + 1 + 2 * sizeof(uint32_t), message, size);
if (connection->ssb->verbose) if (connection->ssb->verbose)
{ {
tf_printf(MAGENTA "%s RPC SEND" RESET " end/error=%s stream=%s type=%s RN=%d: [%zd B] %.*s\n", connection->name, tf_printf(MAGENTA "%s RPC SEND" RESET " end/error=%s stream=%s type=%s RN=%d: [%zd B] %.*s\n", connection->name, (flags & k_ssb_rpc_flag_end_error) ? "true" : "false",
(flags & k_ssb_rpc_flag_end_error) ? "true" : "false", (flags & k_ssb_rpc_flag_stream) ? "true" : "false", k_ssb_type_names[flags & k_ssb_rpc_mask_type], (flags & k_ssb_rpc_flag_stream) ? "true" : "false", k_ssb_type_names[flags & k_ssb_rpc_mask_type], request_number, size,
request_number, size, (flags & k_ssb_rpc_mask_type) == k_ssb_rpc_flag_binary ? 0 : (int)size, message); (flags & k_ssb_rpc_mask_type) == k_ssb_rpc_flag_binary ? 0 : (int)size, message);
} }
_tf_ssb_connection_add_debug_message(connection, true, flags & k_ssb_rpc_mask_send, 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_ssb_connection_box_stream_send(connection, combined, 1 + 2 * sizeof(uint32_t) + size);
@ -792,14 +790,13 @@ void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags,
} }
void tf_ssb_connection_rpc_send_json( 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) 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)
{ {
JSContext* context = connection->ssb->context; JSContext* context = connection->ssb->context;
JSValue json = JS_JSONStringify(context, message, JS_NULL, JS_NULL); JSValue json = JS_JSONStringify(context, message, JS_NULL, JS_NULL);
size_t size = 0; size_t size = 0;
const char* json_string = JS_ToCStringLen(context, &size, json); const char* json_string = JS_ToCStringLen(context, &size, json);
tf_ssb_connection_rpc_send( tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_json | (flags & ~k_ssb_rpc_mask_type), request_number, (const uint8_t*)json_string, size, callback, cleanup, user_data);
connection, k_ssb_rpc_flag_json | (flags & ~k_ssb_rpc_mask_type), request_number, (const uint8_t*)json_string, size, callback, cleanup, user_data);
JS_FreeCString(context, json_string); JS_FreeCString(context, json_string);
JS_FreeValue(context, json); JS_FreeValue(context, json);
} }
@ -813,7 +810,7 @@ void tf_ssb_connection_rpc_send_error(tf_ssb_connection_t* connection, uint8_t f
JS_SetPropertyStr(context, message, "stack", JS_NewString(context, stack ? stack : "stack unavailable")); JS_SetPropertyStr(context, message, "stack", JS_NewString(context, stack ? stack : "stack unavailable"));
JS_SetPropertyStr(context, message, "message", JS_NewString(context, error)); JS_SetPropertyStr(context, message, "message", JS_NewString(context, error));
tf_ssb_connection_rpc_send_json( tf_ssb_connection_rpc_send_json(
connection, ((flags & k_ssb_rpc_flag_stream) ? (k_ssb_rpc_flag_stream) : 0) | k_ssb_rpc_flag_end_error, request_number, message, NULL, NULL, NULL); connection, ((flags & k_ssb_rpc_flag_stream) ? (k_ssb_rpc_flag_stream) : 0) | k_ssb_rpc_flag_end_error, request_number, message, NULL, NULL, NULL);
JS_FreeValue(context, message); JS_FreeValue(context, message);
tf_free((void*)stack); tf_free((void*)stack);
} }
@ -1006,7 +1003,7 @@ static bool _tf_ssb_verify_and_strip_signature_internal(JSContext* context, JSVa
} }
bool tf_ssb_verify_and_strip_signature( bool tf_ssb_verify_and_strip_signature(
JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, bool* out_sequence_before_author) JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, bool* out_sequence_before_author)
{ {
if (_tf_ssb_verify_and_strip_signature_internal(context, val, out_id, out_id_size, out_signature, out_signature_size)) if (_tf_ssb_verify_and_strip_signature_internal(context, val, out_id, out_id_size, out_signature, out_signature_size))
{ {
@ -1528,9 +1525,8 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
tf_ssb_id_bin_to_str(id, sizeof(id), connection->serverpub); tf_ssb_id_bin_to_str(id, sizeof(id), connection->serverpub);
if (connection->ssb->verbose) if (connection->ssb->verbose)
{ {
tf_printf(CYAN "%s RPC RECV" RESET " end/error=%s stream=%s type=%s RN=%d: [%zd B] %.*s\n", connection->name, tf_printf(CYAN "%s RPC RECV" RESET " end/error=%s stream=%s type=%s RN=%d: [%zd B] %.*s\n", connection->name, (flags & k_ssb_rpc_flag_end_error) ? "true" : "false",
(flags & k_ssb_rpc_flag_end_error) ? "true" : "false", (flags & k_ssb_rpc_flag_stream) ? "true" : "false", (flags & k_ssb_rpc_flag_stream) ? "true" : "false", k_ssb_type_names[flags & k_ssb_rpc_mask_type], request_number, size, (int)size, message);
k_ssb_type_names[flags & k_ssb_rpc_mask_type], request_number, size, (int)size, message);
} }
JSContext* context = connection->ssb->context; JSContext* context = connection->ssb->context;
JSValue val = JS_ParseJSON(context, (const char*)message, size, NULL); JSValue val = JS_ParseJSON(context, (const char*)message, size, NULL);
@ -1589,9 +1585,8 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
{ {
if (connection->ssb->verbose) if (connection->ssb->verbose)
{ {
tf_printf(CYAN "%s RPC RECV" RESET " end/error=%s stream=%s type=%s RN=%d: [%zd B]\n", connection->name, tf_printf(CYAN "%s RPC RECV" RESET " end/error=%s stream=%s type=%s RN=%d: [%zd B]\n", connection->name, (flags & k_ssb_rpc_flag_end_error) ? "true" : "false",
(flags & k_ssb_rpc_flag_end_error) ? "true" : "false", (flags & k_ssb_rpc_flag_stream) ? "true" : "false", (flags & k_ssb_rpc_flag_stream) ? "true" : "false", k_ssb_type_names[flags & k_ssb_rpc_mask_type], request_number, size);
k_ssb_type_names[flags & k_ssb_rpc_mask_type], request_number, size);
} }
tf_ssb_rpc_callback_t* callback = NULL; tf_ssb_rpc_callback_t* callback = NULL;
void* user_data = NULL; void* user_data = NULL;
@ -1627,7 +1622,7 @@ static void _tf_ssb_connection_rpc_recv_push(tf_ssb_connection_t* connection, co
while (size_left > 0) while (size_left > 0)
{ {
size_t copy_size = size_t copy_size =
(connection->rpc_recv_size + size_left > sizeof(connection->rpc_recv_buffer)) ? sizeof(connection->rpc_recv_buffer) - connection->rpc_recv_size : size_left; (connection->rpc_recv_size + size_left > sizeof(connection->rpc_recv_buffer)) ? sizeof(connection->rpc_recv_buffer) - connection->rpc_recv_size : size_left;
if (copy_size == 0) if (copy_size == 0)
{ {
_tf_ssb_connection_close(connection, "recv buffer overflow"); _tf_ssb_connection_close(connection, "recv buffer overflow");
@ -1700,8 +1695,7 @@ static bool _tf_ssb_connection_box_stream_recv(tf_ssb_connection_t* connection)
memcpy(connection->box_stream_buf, connection->body_auth_tag, sizeof(connection->body_auth_tag)); memcpy(connection->box_stream_buf, connection->body_auth_tag, sizeof(connection->body_auth_tag));
if (_tf_ssb_connection_recv_pop(connection, connection->box_stream_buf + 16, connection->body_len)) if (_tf_ssb_connection_recv_pop(connection, connection->box_stream_buf + 16, connection->body_len))
{ {
if (crypto_secretbox_open_easy( if (crypto_secretbox_open_easy(connection->secretbox_buf, connection->box_stream_buf, 16 + connection->body_len, connection->nonce, connection->s_to_c_box_key) != 0)
connection->secretbox_buf, connection->box_stream_buf, 16 + connection->body_len, connection->nonce, connection->s_to_c_box_key) != 0)
{ {
_tf_ssb_connection_close(connection, "failed to open secret box"); _tf_ssb_connection_close(connection, "failed to open secret box");
return false; return false;
@ -2377,7 +2371,7 @@ void tf_ssb_destroy(tf_ssb_t* ssb)
tf_printf("Waiting for closes.\n"); tf_printf("Waiting for closes.\n");
while (ssb->broadcast_listener.data || ssb->broadcast_sender.data || ssb->broadcast_timer.data || ssb->broadcast_cleanup_timer.data || ssb->trace_timer.data || while (ssb->broadcast_listener.data || ssb->broadcast_sender.data || ssb->broadcast_timer.data || ssb->broadcast_cleanup_timer.data || ssb->trace_timer.data ||
ssb->server.data || ssb->ref_count) ssb->server.data || ssb->ref_count)
{ {
uv_run(ssb->loop, UV_RUN_ONCE); uv_run(ssb->loop, UV_RUN_ONCE);
} }
@ -2605,7 +2599,7 @@ tf_ssb_connection_t* tf_ssb_connection_create(tf_ssb_t* ssb, const char* host, c
} }
static void _tf_ssb_connection_tunnel_callback( static void _tf_ssb_connection_tunnel_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
tf_ssb_connection_t* tunnel = user_data; tf_ssb_connection_t* tunnel = user_data;
if (flags & k_ssb_rpc_flag_end_error) if (flags & k_ssb_rpc_flag_end_error)
@ -2949,7 +2943,7 @@ static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broad
for (tf_ssb_broadcast_t* node = ssb->broadcasts; node; node = node->next) for (tf_ssb_broadcast_t* node = ssb->broadcasts; node; node = node->next)
{ {
if (node->addr.sin_family == broadcast->addr.sin_family && node->addr.sin_port == broadcast->addr.sin_port && if (node->addr.sin_family == broadcast->addr.sin_family && node->addr.sin_port == broadcast->addr.sin_port &&
node->addr.sin_addr.s_addr == broadcast->addr.sin_addr.s_addr && memcmp(node->pub, broadcast->pub, sizeof(node->pub)) == 0) node->addr.sin_addr.s_addr == broadcast->addr.sin_addr.s_addr && memcmp(node->pub, broadcast->pub, sizeof(node->pub)) == 0)
{ {
node->mtime = time(NULL); node->mtime = time(NULL);
return; return;
@ -3001,7 +2995,7 @@ static void _tf_ssb_on_broadcast_listener_recv(uv_udp_t* handle, ssize_t nread,
} }
void tf_ssb_visit_broadcasts( void tf_ssb_visit_broadcasts(
tf_ssb_t* ssb, void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data), void* user_data) tf_ssb_t* ssb, void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data), void* user_data)
{ {
time_t now = time(NULL); time_t now = time(NULL);
tf_ssb_broadcast_t* next = NULL; tf_ssb_broadcast_t* next = NULL;
@ -3304,7 +3298,7 @@ JSValue tf_ssb_connection_get_object(tf_ssb_connection_t* connection)
} }
void tf_ssb_add_message_added_callback( void tf_ssb_add_message_added_callback(
tf_ssb_t* ssb, void (*callback)(tf_ssb_t* ssb, const char* id, void* user_data), void (*cleanup)(tf_ssb_t* ssb, void* user_data), void* user_data) tf_ssb_t* ssb, void (*callback)(tf_ssb_t* ssb, const char* id, void* user_data), void (*cleanup)(tf_ssb_t* ssb, void* user_data), void* user_data)
{ {
tf_ssb_message_added_callback_node_t* node = tf_malloc(sizeof(tf_ssb_message_added_callback_node_t)); tf_ssb_message_added_callback_node_t* node = tf_malloc(sizeof(tf_ssb_message_added_callback_node_t));
*node = (tf_ssb_message_added_callback_node_t) { *node = (tf_ssb_message_added_callback_node_t) {
@ -3370,12 +3364,12 @@ void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* id, JSValue message_
{ {
continue; continue;
} }
tf_ssb_connection_message_request_t* message_request = bsearch( tf_ssb_connection_message_request_t* message_request =
author_string, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare); bsearch(author_string, connection->message_requests, connection->message_requests_count, sizeof(tf_ssb_connection_message_request_t), _message_request_compare);
if (message_request) if (message_request)
{ {
tf_ssb_connection_rpc_send_json( tf_ssb_connection_rpc_send_json(
connection, k_ssb_rpc_flag_stream, message_request->request_number, message_request->keys ? message_keys : message, NULL, NULL, NULL); connection, k_ssb_rpc_flag_stream, message_request->request_number, message_request->keys ? message_keys : message, NULL, NULL, NULL);
} }
} }
@ -3386,7 +3380,7 @@ void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* id, JSValue message_
} }
void tf_ssb_add_blob_want_added_callback( void tf_ssb_add_blob_want_added_callback(
tf_ssb_t* ssb, void (*callback)(tf_ssb_t* ssb, const char* id, void* user_data), void (*cleanup)(tf_ssb_t* ssb, void* user_data), void* user_data) tf_ssb_t* ssb, void (*callback)(tf_ssb_t* ssb, const char* id, void* user_data), void (*cleanup)(tf_ssb_t* ssb, void* user_data), void* user_data)
{ {
tf_ssb_blob_want_added_callback_node_t* node = tf_malloc(sizeof(tf_ssb_blob_want_added_callback_node_t)); tf_ssb_blob_want_added_callback_node_t* node = tf_malloc(sizeof(tf_ssb_blob_want_added_callback_node_t));
*node = (tf_ssb_blob_want_added_callback_node_t) { *node = (tf_ssb_blob_want_added_callback_node_t) {
@ -3625,8 +3619,8 @@ JSValue tf_ssb_get_disconnection_debug(tf_ssb_t* ssb, JSContext* context)
JS_SetPropertyStr(context, message, "flags", JS_NewInt32(context, ssb->debug_close[i].messages[j]->flags)); JS_SetPropertyStr(context, message, "flags", JS_NewInt32(context, ssb->debug_close[i].messages[j]->flags));
JS_SetPropertyStr(context, message, "request_number", JS_NewInt32(context, ssb->debug_close[i].messages[j]->request_number)); JS_SetPropertyStr(context, message, "request_number", JS_NewInt32(context, ssb->debug_close[i].messages[j]->request_number));
JS_SetPropertyStr(context, message, "timestamp", JS_NewFloat64(context, ssb->debug_close[i].messages[j]->timestamp)); JS_SetPropertyStr(context, message, "timestamp", JS_NewFloat64(context, ssb->debug_close[i].messages[j]->timestamp));
JS_SetPropertyStr(context, message, "payload", JS_SetPropertyStr(
JS_NewStringLen(context, (const char*)ssb->debug_close[i].messages[j]->data, ssb->debug_close[i].messages[j]->size)); context, message, "payload", JS_NewStringLen(context, (const char*)ssb->debug_close[i].messages[j]->data, ssb->debug_close[i].messages[j]->size));
JS_SetPropertyUint32(context, messages, j, message); JS_SetPropertyUint32(context, messages, j, message);
} }
} }
@ -3720,7 +3714,7 @@ static void _tf_ssb_connection_after_work_callback(uv_work_t* work, int status)
} }
void tf_ssb_connection_run_work(tf_ssb_connection_t* connection, void (*work_callback)(tf_ssb_connection_t* connection, void* user_data), void tf_ssb_connection_run_work(tf_ssb_connection_t* connection, void (*work_callback)(tf_ssb_connection_t* connection, void* user_data),
void (*after_work_callback)(tf_ssb_connection_t* connection, int result, void* user_data), void* user_data) void (*after_work_callback)(tf_ssb_connection_t* connection, int result, void* user_data), void* user_data)
{ {
connection_work_t* work = tf_malloc(sizeof(connection_work_t)); connection_work_t* work = tf_malloc(sizeof(connection_work_t));
*work = (connection_work_t) *work = (connection_work_t)

View File

@ -28,7 +28,7 @@ static void _tf_ssb_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_change_t
{ {
char key[k_id_base64_len]; char key[k_id_base64_len];
if (tf_ssb_connection_get_host(connection) && *tf_ssb_connection_get_host(connection) && tf_ssb_connection_get_port(connection) && if (tf_ssb_connection_get_host(connection) && *tf_ssb_connection_get_host(connection) && tf_ssb_connection_get_port(connection) &&
tf_ssb_connection_get_id(connection, key, sizeof(key))) tf_ssb_connection_get_id(connection, key, sizeof(key)))
{ {
tf_ssb_connections_set_attempted(connections, tf_ssb_connection_get_host(connection), tf_ssb_connection_get_port(connection), key); tf_ssb_connections_set_attempted(connections, tf_ssb_connection_get_host(connection), tf_ssb_connection_get_port(connection), key);
} }
@ -53,8 +53,8 @@ static bool _tf_ssb_connections_get_next_connection(tf_ssb_connections_t* connec
bool result = false; bool result = false;
sqlite3_stmt* statement; sqlite3_stmt* statement;
sqlite3* db = tf_ssb_acquire_db_reader(connections->ssb); sqlite3* db = tf_ssb_acquire_db_reader(connections->ssb);
if (sqlite3_prepare(db, "SELECT host, port, key FROM connections WHERE last_attempt IS NULL OR (strftime('%s', 'now') - last_attempt > ?1) ORDER BY last_attempt LIMIT 1", if (sqlite3_prepare(db, "SELECT host, port, key FROM connections WHERE last_attempt IS NULL OR (strftime('%s', 'now') - last_attempt > ?1) ORDER BY last_attempt LIMIT 1", -1,
-1, &statement, NULL) == SQLITE_OK) &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_int(statement, 1, 60000) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW) if (sqlite3_bind_int(statement, 1, 60000) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
{ {
@ -179,11 +179,10 @@ static void _tf_ssb_connections_update_work(uv_work_t* work)
sqlite3* db = tf_ssb_acquire_db_writer(update->ssb); sqlite3* db = tf_ssb_acquire_db_writer(update->ssb);
if (update->attempted) if (update->attempted)
{ {
if (sqlite3_prepare(db, "UPDATE connections SET last_attempt = strftime('%s', 'now') WHERE host = ?1 AND port = ?2 AND key = ?3", -1, &statement, NULL) == if (sqlite3_prepare(db, "UPDATE connections SET last_attempt = strftime('%s', 'now') WHERE host = ?1 AND port = ?2 AND key = ?3", -1, &statement, NULL) == SQLITE_OK)
SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, update->host, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, update->port) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, update->host, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, update->port) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, update->key, -1, NULL) == SQLITE_OK) sqlite3_bind_text(statement, 3, update->key, -1, NULL) == SQLITE_OK)
{ {
if (sqlite3_step(statement) != SQLITE_DONE) if (sqlite3_step(statement) != SQLITE_DONE)
{ {
@ -195,11 +194,10 @@ static void _tf_ssb_connections_update_work(uv_work_t* work)
} }
else if (update->succeeded) else if (update->succeeded)
{ {
if (sqlite3_prepare(db, "UPDATE connections SET last_success = strftime('%s', 'now') WHERE host = ?1 AND port = ?2 AND key = ?3", -1, &statement, NULL) == if (sqlite3_prepare(db, "UPDATE connections SET last_success = strftime('%s', 'now') WHERE host = ?1 AND port = ?2 AND key = ?3", -1, &statement, NULL) == SQLITE_OK)
SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, update->host, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, update->port) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, update->host, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, update->port) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, update->key, -1, NULL) == SQLITE_OK) sqlite3_bind_text(statement, 3, update->key, -1, NULL) == SQLITE_OK)
{ {
if (sqlite3_step(statement) != SQLITE_DONE) if (sqlite3_step(statement) != SQLITE_DONE)
{ {
@ -214,7 +212,7 @@ static void _tf_ssb_connections_update_work(uv_work_t* work)
if (sqlite3_prepare(db, "INSERT INTO connections (host, port, key) VALUES (?1, ?2, ?3) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "INSERT INTO connections (host, port, key) VALUES (?1, ?2, ?3) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, update->host, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, update->port) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, update->host, -1, NULL) == SQLITE_OK && sqlite3_bind_int(statement, 2, update->port) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, update->key, -1, NULL) == SQLITE_OK) sqlite3_bind_text(statement, 3, update->key, -1, NULL) == SQLITE_OK)
{ {
int r = sqlite3_step(statement); int r = sqlite3_step(statement);
if (r != SQLITE_DONE) if (r != SQLITE_DONE)

View File

@ -94,51 +94,51 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
} }
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS messages (" "CREATE TABLE IF NOT EXISTS messages ("
" author TEXT," " author TEXT,"
" id TEXT PRIMARY KEY," " id TEXT PRIMARY KEY,"
" sequence INTEGER," " sequence INTEGER,"
" timestamp REAL," " timestamp REAL,"
" previous TEXT," " previous TEXT,"
" hash TEXT," " hash TEXT,"
" content TEXT," " content TEXT,"
" signature TEXT," " signature TEXT,"
" sequence_before_author INTEGER," " sequence_before_author INTEGER,"
" UNIQUE(author, sequence)" " UNIQUE(author, sequence)"
")"); ")");
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_id_index ON messages (author, id)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_id_index ON messages (author, id)");
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_sequence_index ON messages (author, sequence)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_sequence_index ON messages (author, sequence)");
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)");
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_timestamp_index ON messages (timestamp)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_timestamp_index ON messages (timestamp)");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS blobs (" "CREATE TABLE IF NOT EXISTS blobs ("
" id TEXT PRIMARY KEY," " id TEXT PRIMARY KEY,"
" content BLOB," " content BLOB,"
" created INTEGER" " created INTEGER"
")"); ")");
_tf_ssb_db_exec(db, "DROP TABLE IF EXISTS blob_wants"); _tf_ssb_db_exec(db, "DROP TABLE IF EXISTS blob_wants");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS properties (" "CREATE TABLE IF NOT EXISTS properties ("
" id TEXT," " id TEXT,"
" key TEXT," " key TEXT,"
" value TEXT," " value TEXT,"
" UNIQUE(id, key)" " UNIQUE(id, key)"
")"); ")");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS connections (" "CREATE TABLE IF NOT EXISTS connections ("
" host TEXT," " host TEXT,"
" port INTEGER," " port INTEGER,"
" key TEXT," " key TEXT,"
" last_attempt INTEGER," " last_attempt INTEGER,"
" last_success INTEGER," " last_success INTEGER,"
" UNIQUE(host, port, key)" " UNIQUE(host, port, key)"
")"); ")");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS identities (" "CREATE TABLE IF NOT EXISTS identities ("
" user TEXT," " user TEXT,"
" public_key TEXT UNIQUE," " public_key TEXT UNIQUE,"
" private_key TEXT UNIQUE" " private_key TEXT UNIQUE"
")"); ")");
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS identities_user ON identities (user, public_key)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS identities_user ON identities (user, public_key)");
bool populate_fts = false; bool populate_fts = false;
@ -165,40 +165,39 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
tf_printf("Done.\n"); tf_printf("Done.\n");
} }
_tf_ssb_db_exec( _tf_ssb_db_exec(db, "CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN INSERT INTO messages_fts(rowid, content) VALUES (new.rowid, new.content); END");
db, "CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN INSERT INTO messages_fts(rowid, content) VALUES (new.rowid, new.content); END");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN INSERT INTO messages_fts(messages_fts, rowid, content) VALUES ('delete', old.rowid, " "CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN INSERT INTO messages_fts(messages_fts, rowid, content) VALUES ('delete', old.rowid, "
"old.content); END"); "old.content); END");
if (!_tf_ssb_db_has_rows(db, "PRAGMA table_list('messages_refs')")) if (!_tf_ssb_db_has_rows(db, "PRAGMA table_list('messages_refs')"))
{ {
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TABLE IF NOT EXISTS messages_refs (" "CREATE TABLE IF NOT EXISTS messages_refs ("
" message TEXT, " " message TEXT, "
" ref TEXT, " " ref TEXT, "
" UNIQUE(message, ref)" " UNIQUE(message, ref)"
")"); ")");
tf_printf("Populating messages_refs...\n"); tf_printf("Populating messages_refs...\n");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"INSERT INTO messages_refs(message, ref) " "INSERT INTO messages_refs(message, ref) "
"SELECT messages.id, j.value FROM messages, json_tree(messages.content) as j WHERE " "SELECT messages.id, j.value FROM messages, json_tree(messages.content) as j WHERE "
"j.value LIKE '&%.sha256' OR " "j.value LIKE '&%.sha256' OR "
"j.value LIKE '%%%.sha256' OR " "j.value LIKE '%%%.sha256' OR "
"j.value LIKE '@%.ed25519' " "j.value LIKE '@%.ed25519' "
"ON CONFLICT DO NOTHING"); "ON CONFLICT DO NOTHING");
tf_printf("Done.\n"); tf_printf("Done.\n");
} }
_tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS messages_ai_refs"); _tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS messages_ai_refs");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE TRIGGER IF NOT EXISTS messages_ai_refs AFTER INSERT ON messages BEGIN " "CREATE TRIGGER IF NOT EXISTS messages_ai_refs AFTER INSERT ON messages BEGIN "
"INSERT INTO messages_refs(message, ref) " "INSERT INTO messages_refs(message, ref) "
"SELECT DISTINCT new.id, j.value FROM json_tree(new.content) as j WHERE " "SELECT DISTINCT new.id, j.value FROM json_tree(new.content) as j WHERE "
"j.value LIKE '&%.sha256' OR " "j.value LIKE '&%.sha256' OR "
"j.value LIKE '%%%.sha256' OR " "j.value LIKE '%%%.sha256' OR "
"j.value LIKE '@%.ed25519' " "j.value LIKE '@%.ed25519' "
"ON CONFLICT DO NOTHING; END"); "ON CONFLICT DO NOTHING; END");
_tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS messages_ad_refs"); _tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS messages_ad_refs");
_tf_ssb_db_exec(db, "CREATE TRIGGER IF NOT EXISTS messages_ad_refs AFTER DELETE ON messages BEGIN DELETE FROM messages_refs WHERE messages_refs.message = old.id; END"); _tf_ssb_db_exec(db, "CREATE TRIGGER IF NOT EXISTS messages_ad_refs AFTER DELETE ON messages BEGIN DELETE FROM messages_refs WHERE messages_refs.message = old.id; END");
@ -206,14 +205,14 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_refs_ref_idx ON messages_refs (ref)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_refs_ref_idx ON messages_refs (ref)");
_tf_ssb_db_exec(db, "DROP VIEW IF EXISTS blob_wants_view"); _tf_ssb_db_exec(db, "DROP VIEW IF EXISTS blob_wants_view");
_tf_ssb_db_exec(db, _tf_ssb_db_exec(db,
"CREATE VIEW IF NOT EXISTS blob_wants_view (id, timestamp) AS " "CREATE VIEW IF NOT EXISTS blob_wants_view (id, timestamp) AS "
" SELECT messages_refs.ref AS id, messages.timestamp AS timestamp " " SELECT messages_refs.ref AS id, messages.timestamp AS timestamp "
" FROM messages_refs " " FROM messages_refs "
" JOIN messages ON messages.id = messages_refs.message " " JOIN messages ON messages.id = messages_refs.message "
" LEFT OUTER JOIN blobs ON messages_refs.ref = blobs.id " " LEFT OUTER JOIN blobs ON messages_refs.ref = blobs.id "
" WHERE blobs.id IS NULL " " WHERE blobs.id IS NULL "
" AND LENGTH(messages_refs.ref) = 52 " " AND LENGTH(messages_refs.ref) = 52 "
" AND messages_refs.ref LIKE '&%.sha256'"); " AND messages_refs.ref LIKE '&%.sha256'");
bool need_add_sequence_before_author = true; bool need_add_sequence_before_author = true;
bool need_convert_timestamp_to_real = false; bool need_convert_timestamp_to_real = false;
@ -270,7 +269,7 @@ static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author,
if (sqlite3_prepare(db, "SELECT COUNT(*) FROM messages WHERE author = ?1 AND sequence = ?2 AND id = ?3", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "SELECT COUNT(*) FROM messages WHERE author = ?1 AND sequence = ?2 AND id = ?3", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, sequence - 1) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, sequence - 1) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, previous, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW) sqlite3_bind_text(statement, 3, previous, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
{ {
exists = sqlite3_column_int(statement, 0) != 0; exists = sqlite3_column_int(statement, 0) != 0;
} }
@ -281,7 +280,7 @@ static bool _tf_ssb_db_previous_message_exists(sqlite3* db, const char* author,
} }
static int64_t _tf_ssb_db_store_message_raw(tf_ssb_t* ssb, const char* id, const char* previous, const char* author, int64_t sequence, double timestamp, const char* content, static int64_t _tf_ssb_db_store_message_raw(tf_ssb_t* ssb, const char* id, const char* previous, const char* author, int64_t sequence, double timestamp, const char* content,
size_t content_len, const char* signature, bool sequence_before_author) size_t content_len, const char* signature, bool sequence_before_author)
{ {
sqlite3* db = tf_ssb_acquire_db_writer(ssb); sqlite3* db = tf_ssb_acquire_db_writer(ssb);
int64_t last_row_id = -1; int64_t last_row_id = -1;
@ -289,16 +288,16 @@ static int64_t _tf_ssb_db_store_message_raw(tf_ssb_t* ssb, const char* id, const
if (_tf_ssb_db_previous_message_exists(db, author, sequence, previous)) if (_tf_ssb_db_previous_message_exists(db, author, sequence, previous))
{ {
const char* query = "INSERT INTO messages (id, previous, author, sequence, timestamp, content, hash, signature, sequence_before_author) VALUES (?, ?, ?, ?, ?, ?, " const char* query = "INSERT INTO messages (id, previous, author, sequence, timestamp, content, hash, signature, sequence_before_author) VALUES (?, ?, ?, ?, ?, ?, "
"?, ?, ?) ON CONFLICT DO NOTHING"; "?, ?, ?) ON CONFLICT DO NOTHING";
sqlite3_stmt* statement; sqlite3_stmt* statement;
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
(previous ? sqlite3_bind_text(statement, 2, previous, -1, NULL) : sqlite3_bind_null(statement, 2)) == SQLITE_OK && (previous ? sqlite3_bind_text(statement, 2, previous, -1, NULL) : sqlite3_bind_null(statement, 2)) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 4, sequence) == SQLITE_OK && sqlite3_bind_text(statement, 3, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 4, sequence) == SQLITE_OK &&
sqlite3_bind_double(statement, 5, timestamp) == SQLITE_OK && sqlite3_bind_text(statement, 6, content, content_len, NULL) == SQLITE_OK && sqlite3_bind_double(statement, 5, timestamp) == SQLITE_OK && sqlite3_bind_text(statement, 6, content, content_len, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 7, "sha256", 6, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 8, signature, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 7, "sha256", 6, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 8, signature, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 9, sequence_before_author) == SQLITE_OK) sqlite3_bind_int(statement, 9, sequence_before_author) == SQLITE_OK)
{ {
int r = sqlite3_step(statement); int r = sqlite3_step(statement);
if (r != SQLITE_DONE) if (r != SQLITE_DONE)
@ -337,9 +336,9 @@ static char* _tf_ssb_db_get_message_blob_wants(tf_ssb_t* ssb, int64_t rowid)
size_t size = 0; size_t size = 0;
if (sqlite3_prepare(db, if (sqlite3_prepare(db,
"SELECT DISTINCT json.value FROM messages, json_tree(messages.content) AS json LEFT OUTER JOIN blobs ON json.value = blobs.id WHERE messages.rowid = ?1 AND " "SELECT DISTINCT json.value FROM messages, json_tree(messages.content) AS json LEFT OUTER JOIN blobs ON json.value = blobs.id WHERE messages.rowid = ?1 AND "
"json.value LIKE '&%%.sha256' AND length(json.value) = ?2 AND blobs.content IS NULL", "json.value LIKE '&%%.sha256' AND length(json.value) = ?2 AND blobs.content IS NULL",
-1, &statement, NULL) == SQLITE_OK) -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_int64(statement, 1, rowid) == SQLITE_OK && sqlite3_bind_int(statement, 2, k_blob_id_len - 1) == SQLITE_OK) if (sqlite3_bind_int64(statement, 1, rowid) == SQLITE_OK && sqlite3_bind_int(statement, 2, k_blob_id_len - 1) == SQLITE_OK)
{ {
@ -404,7 +403,7 @@ static void _tf_ssb_db_store_message_work(uv_work_t* work)
tf_trace_t* trace = tf_ssb_get_trace(store->ssb); tf_trace_t* trace = tf_ssb_get_trace(store->ssb);
tf_trace_begin(trace, "message_store_work"); tf_trace_begin(trace, "message_store_work");
int64_t last_row_id = _tf_ssb_db_store_message_raw(store->ssb, store->id, *store->previous ? store->previous : NULL, store->author, store->sequence, store->timestamp, int64_t last_row_id = _tf_ssb_db_store_message_raw(store->ssb, store->id, *store->previous ? store->previous : NULL, store->author, store->sequence, store->timestamp,
store->content, store->length, store->signature, store->sequence_before_author); store->content, store->length, store->signature, store->sequence_before_author);
if (last_row_id != -1) if (last_row_id != -1)
{ {
store->out_stored = true; store->out_stored = true;
@ -461,7 +460,7 @@ static void _tf_ssb_db_store_message_after_work(uv_work_t* work, int status)
tf_trace_begin(trace, "notify_message_added"); tf_trace_begin(trace, "notify_message_added");
JSContext* context = tf_ssb_get_context(store->ssb); JSContext* context = tf_ssb_get_context(store->ssb);
JSValue formatted = tf_ssb_format_message( JSValue formatted = tf_ssb_format_message(
context, store->previous, store->author, store->sequence, store->timestamp, "sha256", store->content, store->signature, store->sequence_before_author); context, store->previous, store->author, store->sequence, store->timestamp, "sha256", store->content, store->signature, store->sequence_before_author);
JSValue message = JS_NewObject(context); JSValue message = JS_NewObject(context);
JS_SetPropertyStr(context, message, "key", JS_NewString(context, store->id)); JS_SetPropertyStr(context, message, "key", JS_NewString(context, store->id));
JS_SetPropertyStr(context, message, "value", formatted); JS_SetPropertyStr(context, message, "value", formatted);
@ -487,7 +486,7 @@ static void _tf_ssb_db_store_message_after_work(uv_work_t* work, int status)
} }
void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, bool sequence_before_author, void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, bool sequence_before_author,
tf_ssb_db_store_message_callback_t* callback, void* user_data) tf_ssb_db_store_message_callback_t* callback, void* user_data)
{ {
JSValue previousval = JS_GetPropertyStr(context, val, "previous"); JSValue previousval = JS_GetPropertyStr(context, val, "previous");
const char* previous = JS_IsNull(previousval) ? NULL : JS_ToCString(context, previousval); const char* previous = JS_IsNull(previousval) ? NULL : JS_ToCString(context, previousval);
@ -722,8 +721,7 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char*
sqlite3* db = tf_ssb_acquire_db_writer(ssb); sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement; sqlite3_stmt* statement;
if (sqlite3_prepare(db, "INSERT INTO blobs (id, content, created) VALUES (?1, ?2, CAST(strftime('%s') AS INTEGER)) ON CONFLICT DO NOTHING", -1, &statement, NULL) == if (sqlite3_prepare(db, "INSERT INTO blobs (id, content, created) VALUES (?1, ?2, CAST(strftime('%s') AS INTEGER)) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_blob(statement, 2, blob, size, NULL) == SQLITE_OK) if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_blob(statement, 2, blob, size, NULL) == SQLITE_OK)
{ {
@ -762,7 +760,7 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char*
} }
bool tf_ssb_db_get_message_by_author_and_sequence( bool tf_ssb_db_get_message_by_author_and_sequence(
tf_ssb_t* ssb, const char* author, int64_t sequence, char* out_message_id, size_t out_message_id_size, double* out_timestamp, char** out_content) tf_ssb_t* ssb, const char* author, int64_t sequence, char* out_message_id, size_t out_message_id_size, double* out_timestamp, char** out_content)
{ {
bool found = false; bool found = false;
sqlite3_stmt* statement; sqlite3_stmt* statement;
@ -770,8 +768,7 @@ bool tf_ssb_db_get_message_by_author_and_sequence(
sqlite3* db = tf_ssb_acquire_db_reader(ssb); sqlite3* db = tf_ssb_acquire_db_reader(ssb);
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, sequence) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, sequence) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
sqlite3_step(statement) == SQLITE_ROW)
{ {
if (out_message_id) if (out_message_id)
{ {
@ -927,11 +924,10 @@ int tf_ssb_sqlite_authorizer(void* user_data, int action_code, const char* arg0,
break; break;
case SQLITE_READ: case SQLITE_READ:
result = (strcmp(arg0, "blob_wants_view") == 0 || strcmp(arg0, "json_each") == 0 || strcmp(arg0, "json_tree") == 0 || strcmp(arg0, "messages") == 0 || result = (strcmp(arg0, "blob_wants_view") == 0 || strcmp(arg0, "json_each") == 0 || strcmp(arg0, "json_tree") == 0 || strcmp(arg0, "messages") == 0 ||
strcmp(arg0, "messages_fts") == 0 || strcmp(arg0, "messages_fts_idx") == 0 || strcmp(arg0, "messages_fts_config") == 0 || strcmp(arg0, "messages_fts") == 0 || strcmp(arg0, "messages_fts_idx") == 0 || strcmp(arg0, "messages_fts_config") == 0 || strcmp(arg0, "messages_refs") == 0 ||
strcmp(arg0, "messages_refs") == 0 || strcmp(arg0, "messages_refs_message_idx") == 0 || strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "messages_refs_message_idx") == 0 || strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "sqlite_master") == 0 || false)
strcmp(arg0, "sqlite_master") == 0 || false) ? SQLITE_OK
? SQLITE_OK : SQLITE_DENY;
: SQLITE_DENY;
break; break;
case SQLITE_PRAGMA: case SQLITE_PRAGMA:
result = strcmp(arg0, "data_version") == 0 ? SQLITE_OK : SQLITE_DENY; result = strcmp(arg0, "data_version") == 0 ? SQLITE_OK : SQLITE_DENY;
@ -989,7 +985,7 @@ JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue bi
} }
JSValue tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content, JSValue tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content,
const char* signature, bool sequence_before_author) const char* signature, bool sequence_before_author)
{ {
JSValue value = JS_NewObject(context); JSValue value = JS_NewObject(context);
JS_SetPropertyStr(context, value, "previous", (previous && *previous) ? JS_NewString(context, previous) : JS_NULL); JS_SetPropertyStr(context, value, "previous", (previous && *previous) ? JS_NewString(context, previous) : JS_NULL);
@ -1056,7 +1052,7 @@ bool tf_ssb_db_identity_add(tf_ssb_t* ssb, const char* user, const char* public_
if (sqlite3_prepare(db, "INSERT INTO identities (user, public_key, private_key) VALUES (?, ?, ?) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "INSERT INTO identities (user, public_key, private_key) VALUES (?, ?, ?) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, public_key, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, public_key, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, private_key, -1, NULL) == SQLITE_OK) sqlite3_bind_text(statement, 3, private_key, -1, NULL) == SQLITE_OK)
{ {
added = sqlite3_step(statement) == SQLITE_DONE && sqlite3_changes(db) != 0; added = sqlite3_step(statement) == SQLITE_DONE && sqlite3_changes(db) != 0;
if (!added) if (!added)
@ -1137,7 +1133,7 @@ bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const c
if (sqlite3_prepare(db, "SELECT private_key FROM identities WHERE user = ? AND public_key = ?", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "SELECT private_key FROM identities WHERE user = ? AND public_key = ?", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 2, (public_key && *public_key == '@') ? public_key + 1 : public_key, -1, NULL) == SQLITE_OK) sqlite3_bind_text(statement, 2, (public_key && *public_key == '@') ? public_key + 1 : public_key, -1, NULL) == SQLITE_OK)
{ {
if (sqlite3_step(statement) == SQLITE_ROW) if (sqlite3_step(statement) == SQLITE_ROW)
{ {
@ -1273,11 +1269,11 @@ static void _populate_follows_and_blocks(tf_ssb_t* ssb, following_t* entry, foll
sqlite3* db = tf_ssb_acquire_db_reader(ssb); sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL; sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, if (sqlite3_prepare(db,
"SELECT json_extract(content, '$.contact') AS contact, json_extract(content, '$.following'), json_extract(content, '$.blocking') " "SELECT json_extract(content, '$.contact') AS contact, json_extract(content, '$.following'), json_extract(content, '$.blocking') "
"FROM messages " "FROM messages "
"WHERE contact IS NOT NULL AND author = ? AND json_extract(content, '$.type') = 'contact' " "WHERE contact IS NOT NULL AND author = ? AND json_extract(content, '$.type') = 'contact' "
"ORDER BY sequence", "ORDER BY sequence",
-1, &statement, NULL) == SQLITE_OK) -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, entry->id, -1, NULL) == SQLITE_OK) if (sqlite3_bind_text(statement, 1, entry->id, -1, NULL) == SQLITE_OK)
{ {
@ -1485,8 +1481,8 @@ JSValue tf_ssb_db_get_message_by_id(tf_ssb_t* ssb, const char* id, bool is_keys)
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
sqlite3* db = tf_ssb_acquire_db_reader(ssb); sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement; sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT previous, author, id, sequence, timestamp, hash, content, signature, sequence_before_author FROM messages WHERE id = ?", -1, &statement, if (sqlite3_prepare(
NULL) == SQLITE_OK) db, "SELECT previous, author, id, sequence, timestamp, hash, content, signature, sequence_before_author FROM messages WHERE id = ?", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK) if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK)
{ {
@ -1494,8 +1490,8 @@ JSValue tf_ssb_db_get_message_by_id(tf_ssb_t* ssb, const char* id, bool is_keys)
{ {
JSValue message = JS_UNDEFINED; JSValue message = JS_UNDEFINED;
JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1), JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1),
sqlite3_column_int64(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5), sqlite3_column_int64(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5),
(const char*)sqlite3_column_text(statement, 6), (const char*)sqlite3_column_text(statement, 7), sqlite3_column_int(statement, 8)); (const char*)sqlite3_column_text(statement, 6), (const char*)sqlite3_column_text(statement, 7), sqlite3_column_int(statement, 8));
if (is_keys) if (is_keys)
{ {
message = JS_NewObject(context); message = JS_NewObject(context);
@ -1550,7 +1546,7 @@ void tf_ssb_db_forget_stored_connection(tf_ssb_t* ssb, const char* address, int
if (sqlite3_prepare(db, "DELETE FROM connections WHERE host = ? AND port = ? AND key = ?", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "DELETE FROM connections WHERE host = ? AND port = ? AND key = ?", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, address, -1, NULL) != SQLITE_OK || sqlite3_bind_int(statement, 2, port) != SQLITE_OK || if (sqlite3_bind_text(statement, 1, address, -1, NULL) != SQLITE_OK || sqlite3_bind_int(statement, 2, port) != SQLITE_OK ||
sqlite3_bind_text(statement, 3, pubkey, -1, NULL) != SQLITE_OK || sqlite3_step(statement) != SQLITE_DONE) sqlite3_bind_text(statement, 3, pubkey, -1, NULL) != SQLITE_OK || sqlite3_step(statement) != SQLITE_DONE)
{ {
tf_printf("Delete stored connection: %s.\n", sqlite3_errmsg(db)); tf_printf("Delete stored connection: %s.\n", sqlite3_errmsg(db));
} }

View File

@ -16,7 +16,7 @@ bool tf_ssb_db_blob_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_
typedef void(tf_ssb_db_store_message_callback_t)(const char* id, bool stored, void* user_data); typedef void(tf_ssb_db_store_message_callback_t)(const char* id, bool stored, void* user_data);
void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, bool sequence_before_author, void tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id, JSValue val, const char* signature, bool sequence_before_author,
tf_ssb_db_store_message_callback_t* callback, void* user_data); tf_ssb_db_store_message_callback_t* callback, void* user_data);
typedef void(tf_ssb_db_blob_store_callback_t)(const char* id, bool is_new, void* user_data); typedef void(tf_ssb_db_blob_store_callback_t)(const char* id, bool is_new, void* user_data);
void tf_ssb_db_blob_store_async(tf_ssb_t* ssb, const uint8_t* blob, size_t size, tf_ssb_db_blob_store_callback_t* callback, void* user_data); void tf_ssb_db_blob_store_async(tf_ssb_t* ssb, const uint8_t* blob, size_t size, tf_ssb_db_blob_store_callback_t* callback, void* user_data);
@ -24,7 +24,7 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char*
JSValue tf_ssb_db_get_message_by_id(tf_ssb_t* ssb, const char* id, bool is_keys); JSValue tf_ssb_db_get_message_by_id(tf_ssb_t* ssb, const char* id, bool is_keys);
bool tf_ssb_db_get_message_by_author_and_sequence( bool tf_ssb_db_get_message_by_author_and_sequence(
tf_ssb_t* ssb, const char* author, int64_t sequence, char* out_message_id, size_t out_message_id_size, double* out_timestamp, char** out_content); tf_ssb_t* ssb, const char* author, int64_t sequence, char* out_message_id, size_t out_message_id_size, double* out_timestamp, char** out_content);
bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, int64_t* out_sequence, char* out_message_id, size_t out_message_id_size); bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, int64_t* out_sequence, char* out_message_id, size_t out_message_id_size);
JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds, void (*callback)(JSValue row, void* user_data), void* user_data); JSValue tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds, void (*callback)(JSValue row, void* user_data), void* user_data);
@ -40,7 +40,7 @@ void tf_ssb_db_identity_visit_all(tf_ssb_t* ssb, void (*callback)(const char* id
bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const char* public_key, uint8_t* out_private_key, size_t private_key_size); bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const char* public_key, uint8_t* out_private_key, size_t private_key_size);
JSValue tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content, JSValue tf_ssb_format_message(JSContext* context, const char* previous, const char* author, int64_t sequence, double timestamp, const char* hash, const char* content,
const char* signature, bool sequence_before_author); const char* signature, bool sequence_before_author);
typedef struct _tf_ssb_following_t typedef struct _tf_ssb_following_t
{ {

View File

@ -92,8 +92,7 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
sqlite3_stmt* statement; sqlite3_stmt* statement;
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = ?1 AND key = 'path:' || ?2", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = ?1 AND key = 'path:' || ?2", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, path, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, path, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_ROW)
sqlite3_step(statement) == SQLITE_ROW)
{ {
int len = sqlite3_column_bytes(statement, 0); int len = sqlite3_column_bytes(statement, 0);
if (len >= (int)sizeof(app_blob_id)) if (len >= (int)sizeof(app_blob_id))

View File

@ -108,7 +108,7 @@ JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* pr
bool tf_ssb_whoami(tf_ssb_t* ssb, char* out_id, size_t out_id_size); bool tf_ssb_whoami(tf_ssb_t* ssb, char* out_id, size_t out_id_size);
void tf_ssb_visit_broadcasts( void tf_ssb_visit_broadcasts(
tf_ssb_t* ssb, void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data), void* user_data); tf_ssb_t* ssb, void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data), void* user_data);
const char** tf_ssb_get_connection_ids(tf_ssb_t* ssb); const char** tf_ssb_get_connection_ids(tf_ssb_t* ssb);
int tf_ssb_get_connections(tf_ssb_t* ssb, tf_ssb_connection_t** out_connections, int out_connections_count); int tf_ssb_get_connections(tf_ssb_t* ssb, tf_ssb_connection_t** out_connections, int out_connections_count);
@ -124,7 +124,7 @@ bool tf_ssb_id_str_to_bin(uint8_t* bin, const char* str);
bool tf_ssb_id_bin_to_str(char* str, size_t str_size, const uint8_t* bin); bool tf_ssb_id_bin_to_str(char* str, size_t str_size, const uint8_t* bin);
bool tf_ssb_verify_and_strip_signature( bool tf_ssb_verify_and_strip_signature(
JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, bool* out_sequence_before_author); JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, bool* out_sequence_before_author);
void tf_ssb_calculate_message_id(JSContext* context, JSValue message, char* out_id, size_t out_id_size); void tf_ssb_calculate_message_id(JSContext* context, JSValue message, char* out_id, size_t out_id_size);
typedef void(tf_ssb_verify_strip_store_callback_t)(const char* id, bool verified, bool is_new, void* user_data); typedef void(tf_ssb_verify_strip_store_callback_t)(const char* id, bool verified, bool is_new, void* user_data);
void tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, tf_ssb_verify_strip_store_callback_t* callback, void* user_data); void tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, tf_ssb_verify_strip_store_callback_t* callback, void* user_data);
@ -171,19 +171,19 @@ void tf_ssb_add_rpc_callback(tf_ssb_t* ssb, const char** name, tf_ssb_rpc_callba
void tf_ssb_remove_rpc_callback(tf_ssb_t* ssb, const char** name, tf_ssb_rpc_callback_t* callback, void* user_data); void tf_ssb_remove_rpc_callback(tf_ssb_t* ssb, const char** name, tf_ssb_rpc_callback_t* callback, void* user_data);
void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const uint8_t* message, size_t size, tf_ssb_rpc_callback_t* callback, void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const uint8_t* message, size_t size, tf_ssb_rpc_callback_t* callback,
tf_ssb_callback_cleanup_t* cleanup, void* user_data); tf_ssb_callback_cleanup_t* cleanup, void* user_data);
void tf_ssb_connection_rpc_send_json( 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); 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);
void tf_ssb_connection_rpc_send_error(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const char* error); void tf_ssb_connection_rpc_send_error(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const char* error);
void tf_ssb_connection_rpc_send_error_method_not_allowed(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const char* name); void tf_ssb_connection_rpc_send_error_method_not_allowed(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const char* name);
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, 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_t* dependent_connection);
void tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t request_number); void tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t request_number);
typedef void(tf_ssb_scheduled_callback_t)(tf_ssb_connection_t* connection, void* user_data); typedef void(tf_ssb_scheduled_callback_t)(tf_ssb_connection_t* connection, void* user_data);
void tf_ssb_connection_schedule_idle(tf_ssb_connection_t* connection, tf_ssb_scheduled_callback_t* callback, void* user_data); void tf_ssb_connection_schedule_idle(tf_ssb_connection_t* connection, tf_ssb_scheduled_callback_t* callback, void* user_data);
void tf_ssb_connection_run_work(tf_ssb_connection_t* connection, void (*work_callback)(tf_ssb_connection_t* connection, void* user_data), void tf_ssb_connection_run_work(tf_ssb_connection_t* connection, void (*work_callback)(tf_ssb_connection_t* connection, void* user_data),
void (*after_work_callback)(tf_ssb_connection_t* connection, int result, void* user_data), void* user_data); void (*after_work_callback)(tf_ssb_connection_t* connection, int result, void* user_data), void* user_data);
void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection, const char* author, int32_t request_number, bool keys); void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection, const char* author, int32_t request_number, bool keys);
void tf_ssb_connection_remove_new_message_request(tf_ssb_connection_t* connection, const char* author); void tf_ssb_connection_remove_new_message_request(tf_ssb_connection_t* connection, const char* author);

View File

@ -70,8 +70,7 @@ static void _tf_ssb_import_add_app(tf_ssb_t* ssb, const char* user, const char*
const char* text = JS_ToCString(context, json); const char* text = JS_ToCString(context, json);
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES (?1, 'apps', ?2)", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES (?1, 'apps', ?2)", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, text, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, text, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_OK)
sqlite3_step(statement) == SQLITE_OK)
{ {
} }
sqlite3_finalize(statement); sqlite3_finalize(statement);
@ -165,7 +164,7 @@ static bool _tf_ssb_register_app(tf_ssb_t* ssb, const char* user, const char* ap
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES (?1, 'path:' || ?2, ?3)", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES (?1, 'path:' || ?2, ?3)", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, app, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, app, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, id, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE) sqlite3_bind_text(statement, 3, id, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE)
{ {
result = sqlite3_changes(db) != 0; result = sqlite3_changes(db) != 0;
} }
@ -360,7 +359,7 @@ void tf_ssb_import_from_zip(tf_ssb_t* ssb, const char* zip_path, const char* use
if (unzGetCurrentFileInfo64(zip, &info, file_path, sizeof(file_path), NULL, 0, NULL, 0) == UNZ_OK) if (unzGetCurrentFileInfo64(zip, &info, file_path, sizeof(file_path), NULL, 0, NULL, 0) == UNZ_OK)
{ {
if (strncmp(file_path, path, strlen(path)) == 0 && !strchr(file_path + strlen(path) + 1, '/') && strlen(file_path) > strlen(".json") && if (strncmp(file_path, path, strlen(path)) == 0 && !strchr(file_path + strlen(path) + 1, '/') && strlen(file_path) > strlen(".json") &&
strcasecmp(file_path + strlen(file_path) - strlen(".json"), ".json") == 0) strcasecmp(file_path + strlen(file_path) - strlen(".json"), ".json") == 0)
{ {
unz_file_pos pos = { 0 }; unz_file_pos pos = { 0 };
unzGetFilePos(zip, &pos); unzGetFilePos(zip, &pos);

View File

@ -1404,14 +1404,12 @@ static bool _tf_ssb_get_private_key_curve25519(sqlite3* db, const char* user, co
sqlite3_stmt* statement = NULL; sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT private_key FROM identities WHERE user = ? AND public_key = ?", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "SELECT private_key FROM identities WHERE user = ? AND public_key = ?", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, *identity == '@' ? identity + 1 : identity, -1, NULL) == SQLITE_OK)
sqlite3_bind_text(statement, 2, *identity == '@' ? identity + 1 : identity, -1, NULL) == SQLITE_OK)
{ {
while (sqlite3_step(statement) == SQLITE_ROW) while (sqlite3_step(statement) == SQLITE_ROW)
{ {
uint8_t key[crypto_sign_SECRETKEYBYTES] = { 0 }; uint8_t key[crypto_sign_SECRETKEYBYTES] = { 0 };
int length = int length = tf_base64_decode((const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0) - strlen(".ed25519"), key, sizeof(key));
tf_base64_decode((const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0) - strlen(".ed25519"), key, sizeof(key));
if (length == crypto_sign_SECRETKEYBYTES) if (length == crypto_sign_SECRETKEYBYTES)
{ {
success = crypto_sign_ed25519_sk_to_curve25519(out_private_key, key) == 0; success = crypto_sign_ed25519_sk_to_curve25519(out_private_key, key) == 0;
@ -1483,7 +1481,7 @@ static JSValue _tf_ssb_private_message_encrypt(JSContext* context, JSValueConst
memcpy(length_and_key + 1, body_key, sizeof(body_key)); memcpy(length_and_key + 1, body_key, sizeof(body_key));
size_t payload_size = size_t payload_size =
sizeof(nonce) + sizeof(public_key) + (crypto_secretbox_MACBYTES + sizeof(length_and_key)) * recipient_count + crypto_secretbox_MACBYTES + message_size; sizeof(nonce) + sizeof(public_key) + (crypto_secretbox_MACBYTES + sizeof(length_and_key)) * recipient_count + crypto_secretbox_MACBYTES + message_size;
uint8_t* payload = tf_malloc(payload_size); uint8_t* payload = tf_malloc(payload_size);
@ -1578,7 +1576,7 @@ static JSValue _tf_ssb_private_message_decrypt(JSContext* context, JSValueConst
k_recipient_header_bytes = crypto_secretbox_MACBYTES + sizeof(uint8_t) + crypto_secretbox_KEYBYTES k_recipient_header_bytes = crypto_secretbox_MACBYTES + sizeof(uint8_t) + crypto_secretbox_KEYBYTES
}; };
for (uint8_t* p = decoded + crypto_box_NONCEBYTES + crypto_secretbox_KEYBYTES; p <= decoded + decoded_length - k_recipient_header_bytes; for (uint8_t* p = decoded + crypto_box_NONCEBYTES + crypto_secretbox_KEYBYTES; p <= decoded + decoded_length - k_recipient_header_bytes;
p += k_recipient_header_bytes) p += k_recipient_header_bytes)
{ {
uint8_t out[k_recipient_header_bytes] = { 0 }; uint8_t out[k_recipient_header_bytes] = { 0 };
int opened = crypto_secretbox_open_easy(out, p, k_recipient_header_bytes, nonce, shared_secret); int opened = crypto_secretbox_open_easy(out, p, k_recipient_header_bytes, nonce, shared_secret);

View File

@ -46,7 +46,7 @@ static int64_t _get_global_setting_int64(tf_ssb_t* ssb, const char* name, int64_
} }
static void _tf_ssb_rpc_gossip_ping_callback( static void _tf_ssb_rpc_gossip_ping_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
char buffer[256]; char buffer[256];
snprintf(buffer, sizeof(buffer), "%" PRId64, (int64_t)time(NULL) * 1000); snprintf(buffer, sizeof(buffer), "%" PRId64, (int64_t)time(NULL) * 1000);
@ -63,7 +63,7 @@ static void _tf_ssb_rpc_gossip_ping(tf_ssb_connection_t* connection, uint8_t fla
} }
static void _tf_ssb_rpc_blobs_get_callback( static void _tf_ssb_rpc_blobs_get_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
} }
@ -102,7 +102,7 @@ static void _tf_ssb_rpc_blobs_get(tf_ssb_connection_t* connection, uint8_t flags
for (size_t offset = 0; offset < size; offset += k_send_max) for (size_t offset = 0; offset < size; offset += k_send_max)
{ {
tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream, -request_number, blob + offset, tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream, -request_number, blob + offset,
offset + k_send_max <= size ? k_send_max : (size - offset), NULL, NULL, NULL); offset + k_send_max <= size ? k_send_max : (size - offset), NULL, NULL, NULL);
} }
success = true; success = true;
tf_free(blob); tf_free(blob);
@ -111,8 +111,8 @@ static void _tf_ssb_rpc_blobs_get(tf_ssb_connection_t* connection, uint8_t flags
JS_FreeValue(context, arg); JS_FreeValue(context, arg);
} }
JS_FreeValue(context, ids); JS_FreeValue(context, ids);
tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error | k_ssb_rpc_flag_stream, -request_number, tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error | k_ssb_rpc_flag_stream, -request_number, (const uint8_t*)(success ? "true" : "false"),
(const uint8_t*)(success ? "true" : "false"), strlen(success ? "true" : "false"), NULL, NULL, NULL); strlen(success ? "true" : "false"), NULL, NULL, NULL);
} }
static void _tf_ssb_rpc_blobs_has(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) static void _tf_ssb_rpc_blobs_has(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
@ -169,7 +169,7 @@ static void _tf_ssb_request_blob_wants_work(tf_ssb_connection_t* connection, voi
if (sqlite3_prepare(db, "SELECT id FROM blob_wants_view WHERE id > ? AND timestamp > ? ORDER BY id LIMIT ?", -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, "SELECT id FROM blob_wants_view WHERE id > ? AND timestamp > ? ORDER BY id LIMIT ?", -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, blob_wants->last_id, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, timestamp) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, blob_wants->last_id, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, timestamp) == SQLITE_OK &&
sqlite3_bind_int(statement, 3, _countof(work->out_id)) == SQLITE_OK) sqlite3_bind_int(statement, 3, _countof(work->out_id)) == SQLITE_OK)
{ {
while (sqlite3_step(statement) == SQLITE_ROW) while (sqlite3_step(statement) == SQLITE_ROW)
{ {
@ -214,7 +214,7 @@ static void _tf_ssb_rpc_request_more_blobs(tf_ssb_connection_t* connection)
} }
static void _tf_ssb_rpc_blobs_createWants( static void _tf_ssb_rpc_blobs_createWants(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection); tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection);
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
@ -417,7 +417,7 @@ static void _tf_ssb_rpc_blob_store_callback(const char* id, bool is_new, void* u
} }
static void _tf_ssb_rpc_connection_blobs_get_callback( static void _tf_ssb_rpc_connection_blobs_get_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
@ -436,8 +436,8 @@ static void _tf_ssb_rpc_connection_blobs_get_callback(
} }
/* TODO: Should we send the response in the callback? */ /* TODO: Should we send the response in the callback? */
bool stored = true; bool stored = true;
tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_json | k_ssb_rpc_flag_stream | k_ssb_rpc_flag_end_error, -request_number, tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_json | k_ssb_rpc_flag_stream | k_ssb_rpc_flag_end_error, -request_number, (const uint8_t*)(stored ? "true" : "false"),
(const uint8_t*)(stored ? "true" : "false"), strlen(stored ? "true" : "false"), NULL, NULL, NULL); strlen(stored ? "true" : "false"), NULL, NULL, NULL);
} }
} }
@ -471,13 +471,13 @@ static void _tf_ssb_rpc_connection_blobs_get(tf_ssb_connection_t* connection, co
JS_SetPropertyStr(context, message, "args", args); JS_SetPropertyStr(context, message, "args", args);
tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message, tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message,
_tf_ssb_rpc_connection_blobs_get_callback, _tf_ssb_rpc_connection_blobs_get_cleanup, get); _tf_ssb_rpc_connection_blobs_get_callback, _tf_ssb_rpc_connection_blobs_get_cleanup, get);
JS_FreeValue(context, message); JS_FreeValue(context, message);
} }
static void _tf_ssb_rpc_connection_blobs_createWants_callback( static void _tf_ssb_rpc_connection_blobs_createWants_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection); tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection);
if (!blob_wants) if (!blob_wants)
@ -553,7 +553,7 @@ static void _tf_ssb_rpc_connection_blobs_createWants_callback(
} }
static void _tf_ssb_rpc_connection_room_attendants_callback( static void _tf_ssb_rpc_connection_room_attendants_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
@ -628,7 +628,7 @@ static bool _is_error(JSContext* context, JSValue message)
} }
static void _tf_ssb_rpc_connection_tunnel_isRoom_callback( static void _tf_ssb_rpc_connection_tunnel_isRoom_callback(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
@ -647,7 +647,7 @@ static void _tf_ssb_rpc_connection_tunnel_isRoom_callback(
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "source")); JS_SetPropertyStr(context, message, "type", JS_NewString(context, "source"));
JS_SetPropertyStr(context, message, "args", JS_NewArray(context)); JS_SetPropertyStr(context, message, "args", JS_NewArray(context));
tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message, tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message,
_tf_ssb_rpc_connection_room_attendants_callback, NULL, NULL); _tf_ssb_rpc_connection_room_attendants_callback, NULL, NULL);
JS_FreeValue(context, message); JS_FreeValue(context, message);
} }
} }
@ -678,12 +678,13 @@ static void _tf_ssb_connection_send_history_stream_work(tf_ssb_connection_t* con
sqlite3_stmt* statement; sqlite3_stmt* statement;
const int k_max = 32; const int k_max = 32;
if (sqlite3_prepare(db, if (sqlite3_prepare(db,
"SELECT previous, author, id, sequence, timestamp, hash, content, signature, sequence_before_author FROM messages WHERE author = ?1 AND sequence > ?2 AND sequence " "SELECT previous, author, id, sequence, timestamp, hash, content, signature, sequence_before_author FROM messages WHERE author = ?1 AND sequence > ?2 AND "
"< ?3 ORDER BY sequence", "sequence "
-1, &statement, NULL) == SQLITE_OK) "< ?3 ORDER BY sequence",
-1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, request->author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, request->sequence) == SQLITE_OK && if (sqlite3_bind_text(statement, 1, request->author, -1, NULL) == SQLITE_OK && sqlite3_bind_int64(statement, 2, request->sequence) == SQLITE_OK &&
sqlite3_bind_int64(statement, 3, request->sequence + k_max) == SQLITE_OK) sqlite3_bind_int64(statement, 3, request->sequence + k_max) == SQLITE_OK)
{ {
JSMallocFunctions funcs = { 0 }; JSMallocFunctions funcs = { 0 };
tf_get_js_malloc_functions(&funcs); tf_get_js_malloc_functions(&funcs);
@ -696,8 +697,8 @@ static void _tf_ssb_connection_send_history_stream_work(tf_ssb_connection_t* con
request->out_max_sequence_seen = sqlite3_column_int64(statement, 3); request->out_max_sequence_seen = sqlite3_column_int64(statement, 3);
JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1), JSValue formatted = tf_ssb_format_message(context, (const char*)sqlite3_column_text(statement, 0), (const char*)sqlite3_column_text(statement, 1),
sqlite3_column_int64(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5), sqlite3_column_int64(statement, 3), sqlite3_column_double(statement, 4), (const char*)sqlite3_column_text(statement, 5),
(const char*)sqlite3_column_text(statement, 6), (const char*)sqlite3_column_text(statement, 7), sqlite3_column_int(statement, 8)); (const char*)sqlite3_column_text(statement, 6), (const char*)sqlite3_column_text(statement, 7), sqlite3_column_int(statement, 8));
if (request->keys) if (request->keys)
{ {
message = JS_NewObject(context); message = JS_NewObject(context);
@ -744,7 +745,7 @@ static void _tf_ssb_connection_send_history_stream_after_work(tf_ssb_connection_
for (int i = 0; i < request->out_messages_count; i++) for (int i = 0; i < request->out_messages_count; i++)
{ {
tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_json, request->request_number, (const uint8_t*)request->out_messages[i], tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_json, request->request_number, (const uint8_t*)request->out_messages[i],
strlen(request->out_messages[i]), NULL, NULL, NULL); strlen(request->out_messages[i]), NULL, NULL, NULL);
} }
if (!request->out_finished) if (!request->out_finished)
{ {
@ -777,7 +778,7 @@ static void _tf_ssb_connection_send_history_stream(tf_ssb_connection_t* connecti
} }
static void _tf_ssb_rpc_createHistoryStream( static void _tf_ssb_rpc_createHistoryStream(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
JSContext* context = tf_ssb_get_context(ssb); JSContext* context = tf_ssb_get_context(ssb);
@ -897,7 +898,7 @@ static void _tf_ssb_rpc_ebt_replicate_send_clock_after_work(tf_ssb_connection_t*
if (work->out_clock) if (work->out_clock)
{ {
tf_ssb_connection_rpc_send( tf_ssb_connection_rpc_send(
connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_json, -work->request_number, (const uint8_t*)work->out_clock, strlen(work->out_clock), NULL, NULL, NULL); connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_json, -work->request_number, (const uint8_t*)work->out_clock, strlen(work->out_clock), NULL, NULL, NULL);
tf_free(work->out_clock); tf_free(work->out_clock);
} }
tf_free(work); tf_free(work);
@ -1037,7 +1038,7 @@ static void _tf_ssb_rpc_ebt_replicate(tf_ssb_connection_t* connection, uint8_t f
} }
static void _tf_ssb_rpc_ebt_replicate_client( static void _tf_ssb_rpc_ebt_replicate_client(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
_tf_ssb_rpc_ebt_replicate(connection, flags, request_number, args, message, size, user_data); _tf_ssb_rpc_ebt_replicate(connection, flags, request_number, args, message, size, user_data);
} }
@ -1068,7 +1069,7 @@ static void _tf_ssb_rpc_send_ebt_replicate(tf_ssb_connection_t* connection)
} }
static void _tf_ssb_rpc_ebt_replicate_server( static void _tf_ssb_rpc_ebt_replicate_server(
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data) tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
{ {
if (flags & k_ssb_rpc_flag_end_error) if (flags & k_ssb_rpc_flag_end_error)
{ {
@ -1091,7 +1092,7 @@ static void _tf_ssb_rpc_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_chang
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "source")); JS_SetPropertyStr(context, message, "type", JS_NewString(context, "source"));
JS_SetPropertyStr(context, message, "args", JS_NewArray(context)); JS_SetPropertyStr(context, message, "args", JS_NewArray(context));
tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message, tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message,
_tf_ssb_rpc_connection_blobs_createWants_callback, NULL, NULL); _tf_ssb_rpc_connection_blobs_createWants_callback, NULL, NULL);
JS_FreeValue(context, message); JS_FreeValue(context, message);
if (tf_ssb_connection_is_client(connection)) if (tf_ssb_connection_is_client(connection))
@ -1102,8 +1103,8 @@ static void _tf_ssb_rpc_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_chang
JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "isRoom")); JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "isRoom"));
JS_SetPropertyStr(context, message, "name", name); JS_SetPropertyStr(context, message, "name", name);
JS_SetPropertyStr(context, message, "args", JS_NewArray(context)); JS_SetPropertyStr(context, message, "args", JS_NewArray(context));
tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message, tf_ssb_connection_rpc_send_json(
_tf_ssb_rpc_connection_tunnel_isRoom_callback, NULL, NULL); connection, k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), message, _tf_ssb_rpc_connection_tunnel_isRoom_callback, NULL, NULL);
JS_FreeValue(context, message); JS_FreeValue(context, message);
_tf_ssb_rpc_send_ebt_replicate(connection); _tf_ssb_rpc_send_ebt_replicate(connection);
@ -1125,8 +1126,7 @@ static void _tf_ssb_rpc_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_chang
{ {
if (tf_ssb_connection_is_attendant(connections[i])) if (tf_ssb_connection_is_attendant(connections[i]))
{ {
tf_ssb_connection_rpc_send_json( tf_ssb_connection_rpc_send_json(connections[i], k_ssb_rpc_flag_stream, -tf_ssb_connection_get_attendant_request_number(connections[i]), left, NULL, NULL, NULL);
connections[i], k_ssb_rpc_flag_stream, -tf_ssb_connection_get_attendant_request_number(connections[i]), left, NULL, NULL, NULL);
} }
} }
JS_FreeValue(context, left); JS_FreeValue(context, left);
@ -1177,13 +1177,13 @@ static void _tf_ssb_rpc_delete_blobs_work(uv_work_t* work)
const int k_limit = 128; const int k_limit = 128;
int deleted = 0; int deleted = 0;
if (sqlite3_prepare(db, if (sqlite3_prepare(db,
"DELETE FROM blobs WHERE blobs.id IN (" "DELETE FROM blobs WHERE blobs.id IN ("
" SELECT blobs.id FROM blobs " " SELECT blobs.id FROM blobs "
" JOIN messages_refs ON blobs.id = messages_refs.ref " " JOIN messages_refs ON blobs.id = messages_refs.ref "
" JOIN messages ON messages.id = messages_refs.message " " JOIN messages ON messages.id = messages_refs.message "
" WHERE blobs.created < ?1 / 1000 " " WHERE blobs.created < ?1 / 1000 "
" GROUP BY blobs.id HAVING MAX(messages.timestamp) < ?1 LIMIT ?2)", " GROUP BY blobs.id HAVING MAX(messages.timestamp) < ?1 LIMIT ?2)",
-1, &statement, NULL) == SQLITE_OK) -1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_int64(statement, 1, timestamp) == SQLITE_OK && sqlite3_bind_int(statement, 2, k_limit) == SQLITE_OK) if (sqlite3_bind_int64(statement, 1, timestamp) == SQLITE_OK && sqlite3_bind_int(statement, 2, k_limit) == SQLITE_OK)
{ {

View File

@ -715,8 +715,8 @@ static void _close_callback(uv_timer_t* timer)
close_t* data = timer->data; close_t* data = timer->data;
tf_printf("breaking %s %p\n", data->id, data->connection); tf_printf("breaking %s %p\n", data->id, data->connection);
const char* message = "{\"name\":\"Error\",\"message\":\"whoops\",\"stack\":\"nah\"}"; const char* message = "{\"name\":\"Error\",\"message\":\"whoops\",\"stack\":\"nah\"}";
tf_ssb_connection_rpc_send(data->connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error, data->request_number, (const uint8_t*)message, tf_ssb_connection_rpc_send(
strlen(message), NULL, NULL, NULL); data->connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error, data->request_number, (const uint8_t*)message, strlen(message), NULL, NULL, NULL);
uv_close((uv_handle_t*)timer, _timer_close); uv_close((uv_handle_t*)timer, _timer_close);
} }

View File

@ -455,7 +455,6 @@ static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id)
return NULL; return NULL;
} }
static JSValue _import_call(JSContext* context, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst* argv, int flags) static JSValue _import_call(JSContext* context, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst* argv, int flags)
{ {
import_record_t* import = JS_GetOpaque(func_obj, _import_class_id); import_record_t* import = JS_GetOpaque(func_obj, _import_class_id);
@ -1015,8 +1014,7 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length,
memcpy(&promise, begin, sizeof(promise)); memcpy(&promise, begin, sizeof(promise));
memcpy(&exportId, begin + sizeof(promise), sizeof(exportId)); memcpy(&exportId, begin + sizeof(promise), sizeof(exportId));
JSValue result = JSValue result = _task_invokeExport_internal(from, to, exportId, begin + sizeof(promiseid_t) + sizeof(exportid_t), length - sizeof(promiseid_t) - sizeof(exportid_t));
_task_invokeExport_internal(from, to, exportId, begin + sizeof(promiseid_t) + sizeof(exportid_t), length - sizeof(promiseid_t) - sizeof(exportid_t));
if (JS_IsException(result)) if (JS_IsException(result))
{ {
_tf_task_sendPromiseReject(to, from, promise, result); _tf_task_sendPromiseReject(to, from, promise, result);

View File

@ -92,17 +92,17 @@ static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int a
JSAtom atom = JS_NewAtom(context, "onExit"); JSAtom atom = JS_NewAtom(context, "onExit");
JS_DefinePropertyGetSet( JS_DefinePropertyGetSet(
context, taskObject, atom, JS_NewCFunction(context, _taskstub_get_on_exit, "getOnExit", 0), JS_NewCFunction(context, _taskstub_set_on_exit, "setOnExit", 0), 0); context, taskObject, atom, JS_NewCFunction(context, _taskstub_get_on_exit, "getOnExit", 0), JS_NewCFunction(context, _taskstub_set_on_exit, "setOnExit", 0), 0);
JS_FreeAtom(context, atom); JS_FreeAtom(context, atom);
atom = JS_NewAtom(context, "onError"); atom = JS_NewAtom(context, "onError");
JS_DefinePropertyGetSet( JS_DefinePropertyGetSet(
context, taskObject, atom, JS_NewCFunction(context, _taskstub_get_on_error, "getOnError", 0), JS_NewCFunction(context, _taskstub_set_on_error, "setOnError", 0), 0); context, taskObject, atom, JS_NewCFunction(context, _taskstub_get_on_error, "getOnError", 0), JS_NewCFunction(context, _taskstub_set_on_error, "setOnError", 0), 0);
JS_FreeAtom(context, atom); JS_FreeAtom(context, atom);
atom = JS_NewAtom(context, "onPrint"); atom = JS_NewAtom(context, "onPrint");
JS_DefinePropertyGetSet( JS_DefinePropertyGetSet(
context, taskObject, atom, JS_NewCFunction(context, _taskstub_get_on_print, "getOnPrint", 0), JS_NewCFunction(context, _taskstub_set_on_print, "setOnPrint", 0), 0); context, taskObject, atom, JS_NewCFunction(context, _taskstub_get_on_print, "getOnPrint", 0), JS_NewCFunction(context, _taskstub_set_on_print, "setOnPrint", 0), 0);
JS_FreeAtom(context, atom); JS_FreeAtom(context, atom);
JS_SetPropertyStr(context, taskObject, "activate", JS_NewCFunction(context, _taskstub_activate, "activate", 0)); JS_SetPropertyStr(context, taskObject, "activate", JS_NewCFunction(context, _taskstub_activate, "activate", 0));

View File

@ -61,24 +61,24 @@ static void _test_nop(const tf_test_options_t* options)
static void _test_sandbox(const tf_test_options_t* options) static void _test_sandbox(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.onExit = function(code, signal) {\n" "task.onExit = function(code, signal) {\n"
" print('child exited', code, signal);\n" " print('child exited', code, signal);\n"
" if (code === 0 && signal === 0) {\n" " if (code === 0 && signal === 0) {\n"
" exit(1);\n" " exit(1);\n"
" }\n" " }\n"
"};\n" "};\n"
"task.activate();\n" "task.activate();\n"
"File.readFile('out/child.js').then(function(data) {\n" "File.readFile('out/child.js').then(function(data) {\n"
" task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n" " task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n"
" print('child started');\n" " print('child started');\n"
" });\n" " });\n"
"});"); "});");
_write_file("out/child.js", _write_file("out/child.js",
"print('Poking the sandbox. This should fail.');\n" "print('Poking the sandbox. This should fail.');\n"
"let r = pokeSandbox();\n" "let r = pokeSandbox();\n"
"exit(r);\n"); "exit(r);\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -95,21 +95,21 @@ static void _test_sandbox(const tf_test_options_t* options)
static void _test_child(const tf_test_options_t* options) static void _test_child(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.onExit = function(code, signal) {\n" "task.onExit = function(code, signal) {\n"
" print('child exited', code, signal);\n" " print('child exited', code, signal);\n"
" exit(code || signal);\n" " exit(code || signal);\n"
"};\n" "};\n"
"task.activate();\n" "task.activate();\n"
"File.readFile('out/child.js').then(function(data) {\n" "File.readFile('out/child.js').then(function(data) {\n"
" task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n" " task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n"
" print('child started');\n" " print('child started');\n"
" });\n" " });\n"
"});"); "});");
_write_file("out/child.js", _write_file("out/child.js",
"print('I am the child process.');\n" "print('I am the child process.');\n"
"exit(0);\n"); "exit(0);\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -126,28 +126,28 @@ static void _test_child(const tf_test_options_t* options)
static void _test_promise(const tf_test_options_t* options) static void _test_promise(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.activate();\n" "task.activate();\n"
"File.readFile('out/child.js').then(function(data) {\n" "File.readFile('out/child.js').then(function(data) {\n"
" task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n" " task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n"
" task.getExports().then(function(exports) {\n" " task.getExports().then(function(exports) {\n"
" return exports.add(1, 1);\n" " return exports.add(1, 1);\n"
" }).then(function(sum) {\n" " }).then(function(sum) {\n"
" if (sum == 2) {\n" " if (sum == 2) {\n"
" exit(0);\n" " exit(0);\n"
" } else {\n" " } else {\n"
" exit(1);\n" " exit(1);\n"
" }\n" " }\n"
" });\n" " });\n"
" });\n" " });\n"
"});\n"); "});\n");
_write_file("out/child.js", _write_file("out/child.js",
"exports = {\n" "exports = {\n"
" add: function(left, right) {\n" " add: function(left, right) {\n"
" return left + right;\n" " return left + right;\n"
" }\n" " }\n"
"}\n"); "}\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -164,32 +164,32 @@ static void _test_promise(const tf_test_options_t* options)
static void _test_promise_remote_throw(const tf_test_options_t* options) static void _test_promise_remote_throw(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.activate();\n" "task.activate();\n"
"File.readFile('out/child.js').then(function(data) {\n" "File.readFile('out/child.js').then(function(data) {\n"
" task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n" " task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n"
" task.getExports().then(function(exp) {\n" " task.getExports().then(function(exp) {\n"
" return exp.add(1, 1);\n" " return exp.add(1, 1);\n"
" }).then(function(sum) {\n" " }).then(function(sum) {\n"
" exit(1);\n" " exit(1);\n"
" }).catch(function(error) {\n" " }).catch(function(error) {\n"
" print('Caught: ' + error.message);\n" " print('Caught: ' + error.message);\n"
" if (error.stack) {\n" " if (error.stack) {\n"
" print('stack: ' + error.stack);\n" " print('stack: ' + error.stack);\n"
" }\n" " }\n"
" exit(0);\n" " exit(0);\n"
" });\n" " });\n"
" }).catch(function(e) {\n" " }).catch(function(e) {\n"
" print('caught', e.message);\n" " print('caught', e.message);\n"
" });\n" " });\n"
"});\n"); "});\n");
_write_file("out/child.js", _write_file("out/child.js",
"exports = {\n" "exports = {\n"
" add: function(left, right) {\n" " add: function(left, right) {\n"
" throw new Error('fail');\n" " throw new Error('fail');\n"
" }\n" " }\n"
"}\n"); "}\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -206,34 +206,34 @@ static void _test_promise_remote_throw(const tf_test_options_t* options)
static void _test_promise_remote_reject(const tf_test_options_t* options) static void _test_promise_remote_reject(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.activate();\n" "task.activate();\n"
"File.readFile('out/child.js').then(function(data) {\n" "File.readFile('out/child.js').then(function(data) {\n"
" task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n" " task.execute({name: 'child.js', source: utf8Decode(data)}).then(function() {\n"
" task.getExports().then(function(exp) {\n" " task.getExports().then(function(exp) {\n"
" return exp.add(1, 1);\n" " return exp.add(1, 1);\n"
" }).then(function(sum) {\n" " }).then(function(sum) {\n"
" exit(1);\n" " exit(1);\n"
" }).catch(function(error) {\n" " }).catch(function(error) {\n"
" print('Caught: ' + error.message);\n" " print('Caught: ' + error.message);\n"
" if (error.stack) {\n" " if (error.stack) {\n"
" print('stack: ' + error.stack);\n" " print('stack: ' + error.stack);\n"
" }\n" " }\n"
" exit(0);\n" " exit(0);\n"
" });\n" " });\n"
" }).catch(function(e) {\n" " }).catch(function(e) {\n"
" print('caught', e.message);\n" " print('caught', e.message);\n"
" });\n" " });\n"
"});\n"); "});\n");
_write_file("out/child.js", _write_file("out/child.js",
"exports = {\n" "exports = {\n"
" add: function(left, right) {\n" " add: function(left, right) {\n"
" return new Promise(function(resolve, reject) {\n" " return new Promise(function(resolve, reject) {\n"
" reject(new Error('oops'));\n" " reject(new Error('oops'));\n"
" });\n" " });\n"
" }\n" " }\n"
"}\n"); "}\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -250,32 +250,32 @@ static void _test_promise_remote_reject(const tf_test_options_t* options)
static void _test_database(const tf_test_options_t* options) static void _test_database(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var db = new Database('testdb');\n" "var db = new Database('testdb');\n"
"if (db.get('a')) {\n" "if (db.get('a')) {\n"
" exit(1);\n" " exit(1);\n"
"}\n" "}\n"
"db.set('a', 1);\n" "db.set('a', 1);\n"
"if (db.get('a') != 1) {\n" "if (db.get('a') != 1) {\n"
" exit(2);\n" " exit(2);\n"
"}\n" "}\n"
"db.set('b', 2);\n" "db.set('b', 2);\n"
"db.set('c', 3);\n" "db.set('c', 3);\n"
"\n" "\n"
"var expected = ['a', 'b', 'c'];\n" "var expected = ['a', 'b', 'c'];\n"
"var have = db.getAll();\n" "var have = db.getAll();\n"
"for (var i = 0; i < have.length; i++) {\n" "for (var i = 0; i < have.length; i++) {\n"
" var item = have[i];\n" " var item = have[i];\n"
" if (expected.indexOf(item) == -1) {\n" " if (expected.indexOf(item) == -1) {\n"
" print('Did not find ' + item + ' in db.');\n" " print('Did not find ' + item + ' in db.');\n"
" exit(3);\n" " exit(3);\n"
" } else {\n" " } else {\n"
" expected.splice(expected.indexOf(item), 1);\n" " expected.splice(expected.indexOf(item), 1);\n"
" }\n" " }\n"
"}\n" "}\n"
"if (expected.length) {\n" "if (expected.length) {\n"
" print('Expected but did not find: ' + JSON.stringify(expected));\n" " print('Expected but did not find: ' + JSON.stringify(expected));\n"
" exit(4);\n" " exit(4);\n"
"}\n"); "}\n");
char command[256]; char command[256];
unlink("out/test_db0.sqlite"); unlink("out/test_db0.sqlite");
@ -293,9 +293,9 @@ static void _test_database(const tf_test_options_t* options)
static void _test_this(const tf_test_options_t* options) static void _test_this(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.activate.bind(null).apply();\n" "task.activate.bind(null).apply();\n"
"exit(0);\n"); "exit(0);\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -311,21 +311,21 @@ static void _test_this(const tf_test_options_t* options)
static void _test_await(const tf_test_options_t* options) static void _test_await(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"print('hi');\n" "print('hi');\n"
"function foobar() {\n" "function foobar() {\n"
" return new Promise(function(resolve, reject) {\n" " return new Promise(function(resolve, reject) {\n"
" resolve(10);\n" " resolve(10);\n"
" });\n" " });\n"
"}\n" "}\n"
"\n" "\n"
"async function huh() {\n" "async function huh() {\n"
" let v = await foobar();\n" " let v = await foobar();\n"
" print('v => ' + v);\n" " print('v => ' + v);\n"
" if (v != 10) {\n" " if (v != 10) {\n"
" throw new Error('nope');\n" " throw new Error('nope');\n"
" }\n" " }\n"
"}\n" "}\n"
"\n"); "\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -341,21 +341,21 @@ static void _test_await(const tf_test_options_t* options)
static void _test_import(const tf_test_options_t* options) static void _test_import(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"import * as req from './required.js';\n" "import * as req from './required.js';\n"
"if (req.foo() != 12345) {\n" "if (req.foo() != 12345) {\n"
" exit(1);\n" " exit(1);\n"
"}\n"); "}\n");
_write_file("out/required.js", _write_file("out/required.js",
"export function foo() {\n" "export function foo() {\n"
" return 12345;\n" " return 12345;\n"
"}\n"); "}\n");
_write_file("out/bad.js", _write_file("out/bad.js",
"import * as req from './missing.js';\n" "import * as req from './missing.js';\n"
"if (req.foo() != 12345) {\n" "if (req.foo() != 12345) {\n"
" exit(1);\n" " exit(1);\n"
"}\n"); "}\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -397,8 +397,8 @@ static void _test_exit(const tf_test_options_t* options)
static void _test_icu(const tf_test_options_t* options) static void _test_icu(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"print('Hi');\n" "print('Hi');\n"
"print(parseInt('3').toLocaleString());\n"); "print(parseInt('3').toLocaleString());\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -414,39 +414,39 @@ static void _test_icu(const tf_test_options_t* options)
static void _test_uint8array(const tf_test_options_t* options) static void _test_uint8array(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.onExit = function() {\n" "task.onExit = function() {\n"
" print('child exited');\n" " print('child exited');\n"
"};\n" "};\n"
"task.activate();\n" "task.activate();\n"
"File.readFile('out/child.js').then(function(data) {\n" "File.readFile('out/child.js').then(function(data) {\n"
" task.execute({name: 'child.js', source: utf8Decode(data)}).then(async function() {\n" " task.execute({name: 'child.js', source: utf8Decode(data)}).then(async function() {\n"
" print('child started');\n" " print('child started');\n"
" var input = new Uint8Array(10);\n" " var input = new Uint8Array(10);\n"
" for (var i = 0; i < 10; i++) {\n" " for (var i = 0; i < 10; i++) {\n"
" input[i] = i;\n" " input[i] = i;\n"
" }\n" " }\n"
" var test = (await task.getExports()).test;\n" " var test = (await task.getExports()).test;\n"
" var output = new Uint8Array(await test(input));\n" " var output = new Uint8Array(await test(input));\n"
" print('input', input, input.length, input.byteLength);\n" " print('input', input, input.length, input.byteLength);\n"
" print('output', output, output.length, output.byteLength);\n" " print('output', output, output.length, output.byteLength);\n"
" for (var i = 0; i < 10; i++) {\n" " for (var i = 0; i < 10; i++) {\n"
" print(output[i]);\n" " print(output[i]);\n"
" if (output[i] != i) {\n" " if (output[i] != i) {\n"
" print('output[' + i + '] == ' + output[i]);\n" " print('output[' + i + '] == ' + output[i]);\n"
" exit(1);\n" " exit(1);\n"
" }\n" " }\n"
" }\n" " }\n"
" exit(0);\n" " exit(0);\n"
" })\n" " })\n"
"})\n"); "})\n");
_write_file("out/child.js", _write_file("out/child.js",
"exports = {\n" "exports = {\n"
" test: function(data) {\n" " test: function(data) {\n"
" return data;\n" " return data;\n"
" }\n" " }\n"
"}\n"); "}\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -463,31 +463,31 @@ static void _test_uint8array(const tf_test_options_t* options)
static void _test_float(const tf_test_options_t* options) static void _test_float(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"var task = new Task();\n" "var task = new Task();\n"
"task.onExit = function() {\n" "task.onExit = function() {\n"
" print('child exited');\n" " print('child exited');\n"
"};\n" "};\n"
"task.activate();\n" "task.activate();\n"
"File.readFile('out/child.js').then(function(data) {\n" "File.readFile('out/child.js').then(function(data) {\n"
" task.execute({name: 'child.js', source: utf8Decode(data)}).then(async function() {\n" " task.execute({name: 'child.js', source: utf8Decode(data)}).then(async function() {\n"
" print('get exports');\n" " print('get exports');\n"
" let test = (await task.getExports()).test;\n" " let test = (await task.getExports()).test;\n"
" print('calling export');\n" " print('calling export');\n"
" let result = await test(1.2);\n" " let result = await test(1.2);\n"
" print(result);\n" " print(result);\n"
" exit(result == 1.2 ? 0 : 1);\n" " exit(result == 1.2 ? 0 : 1);\n"
" });\n" " });\n"
"});"); "});");
_write_file("out/child.js", _write_file("out/child.js",
"print(\"child\");\n" "print(\"child\");\n"
"exports = {\n" "exports = {\n"
" test: function(value) {\n" " test: function(value) {\n"
" print(value);\n" " print(value);\n"
" return value;\n" " return value;\n"
" }\n" " }\n"
"};\n" "};\n"
"print(\"child ready\");\n"); "print(\"child ready\");\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -504,77 +504,77 @@ static void _test_float(const tf_test_options_t* options)
static void _test_socket(const tf_test_options_t* options) static void _test_socket(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"'use strict';\n" "'use strict';\n"
"\n" "\n"
"var s = new Socket();\n" "var s = new Socket();\n"
"print('connecting');\n" "print('connecting');\n"
"print('before connect', s.isConnected);\n" "print('before connect', s.isConnected);\n"
"s.onError(function(e) {\n" "s.onError(function(e) {\n"
" print(e);\n" " print(e);\n"
"});\n" "});\n"
"print('noDelay', s.noDelay);\n" "print('noDelay', s.noDelay);\n"
"s.noDelay = true;\n" "s.noDelay = true;\n"
"s.connect('www.unprompted.com', 80).then(function() {\n" "s.connect('www.unprompted.com', 80).then(function() {\n"
" print('connected', 'www.unprompted.com', 80, s.isConnected);\n" " print('connected', 'www.unprompted.com', 80, s.isConnected);\n"
" print(s.peerName);\n" " print(s.peerName);\n"
" s.read(function(data) {\n" " s.read(function(data) {\n"
" print('read', data ? data.length : null);\n" " print('read', data ? data.length : null);\n"
" });\n" " });\n"
" s.write('GET / HTTP/1.0\\r\\n\\r\\n');\n" " s.write('GET / HTTP/1.0\\r\\n\\r\\n');\n"
"}).then(function(e) {\n" "}).then(function(e) {\n"
" print('closed 1');\n" " print('closed 1');\n"
"});\n" "});\n"
"\n" "\n"
"var s2 = new Socket();\n" "var s2 = new Socket();\n"
"print('connecting');\n" "print('connecting');\n"
"print('before connect', s2.isConnected);\n" "print('before connect', s2.isConnected);\n"
"s2.onError(function(e) {\n" "s2.onError(function(e) {\n"
" print('error');\n" " print('error');\n"
" print(e);\n" " print(e);\n"
"});\n" "});\n"
"print('noDelay', s2.noDelay);\n" "print('noDelay', s2.noDelay);\n"
"s2.noDelay = true;\n" "s2.noDelay = true;\n"
"s2.connect('www.unprompted.com', 443).then(function() {\n" "s2.connect('www.unprompted.com', 443).then(function() {\n"
" print('connected', 'www.unprompted.com', 443);\n" " print('connected', 'www.unprompted.com', 443);\n"
" s2.read(function(data) {\n" " s2.read(function(data) {\n"
" print('read', data ? data.length : null);\n" " print('read', data ? data.length : null);\n"
" });\n" " });\n"
" return s2.startTls();\n" " return s2.startTls();\n"
"}).then(function() {\n" "}).then(function() {\n"
" print('ready');\n" " print('ready');\n"
" print(s2.peerName);\n" " print(s2.peerName);\n"
" s2.write('GET / HTTP/1.0\\r\\nConnection: close\\r\\n\\r\\n').then(function() {\n" " s2.write('GET / HTTP/1.0\\r\\nConnection: close\\r\\n\\r\\n').then(function() {\n"
" s2.shutdown();\n" " s2.shutdown();\n"
" });\n" " });\n"
"}).catch(function(e) {\n" "}).catch(function(e) {\n"
" print('caught');\n" " print('caught');\n"
" print(e);\n" " print(e);\n"
"});\n" "});\n"
"var s3 = new Socket();\n" "var s3 = new Socket();\n"
"print('connecting s3');\n" "print('connecting s3');\n"
"print('before connect', s3.isConnected);\n" "print('before connect', s3.isConnected);\n"
"s3.onError(function(e) {\n" "s3.onError(function(e) {\n"
" print('error');\n" " print('error');\n"
" print(e);\n" " print(e);\n"
"});\n" "});\n"
"print('noDelay', s3.noDelay);\n" "print('noDelay', s3.noDelay);\n"
"s3.noDelay = true;\n" "s3.noDelay = true;\n"
"s3.connect('0.0.0.0', 443).then(function() {\n" "s3.connect('0.0.0.0', 443).then(function() {\n"
" print('connected', '0.0.0.0', 443);\n" " print('connected', '0.0.0.0', 443);\n"
" s3.read(function(data) {\n" " s3.read(function(data) {\n"
" print('read', data ? data.length : null);\n" " print('read', data ? data.length : null);\n"
" });\n" " });\n"
" return s3.startTls();\n" " return s3.startTls();\n"
"}).then(function() {\n" "}).then(function() {\n"
" print('ready');\n" " print('ready');\n"
" print(s3.peerName);\n" " print(s3.peerName);\n"
" s3.write('GET / HTTP/1.0\\r\\nConnection: close\\r\\n\\r\\n').then(function() {\n" " s3.write('GET / HTTP/1.0\\r\\nConnection: close\\r\\n\\r\\n').then(function() {\n"
" s3.shutdown();\n" " s3.shutdown();\n"
" });\n" " });\n"
"}).catch(function(e) {\n" "}).catch(function(e) {\n"
" print('caught');\n" " print('caught');\n"
" print(e);\n" " print(e);\n"
"});\n"); "});\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -590,18 +590,18 @@ static void _test_socket(const tf_test_options_t* options)
static void _test_file(const tf_test_options_t* options) static void _test_file(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"'use strict';\n" "'use strict';\n"
"File.readFile('out/test.js').then(function(data) {\n" "File.readFile('out/test.js').then(function(data) {\n"
"}).catch(function(error) {\n" "}).catch(function(error) {\n"
" print('ERROR', error);\n" " print('ERROR', error);\n"
" exit(1);\n" " exit(1);\n"
"});\n" "});\n"
"File.readFile('out/missing.txt').then(function(data) {\n" "File.readFile('out/missing.txt').then(function(data) {\n"
" print('READ', utf8Decode(data));\n" " print('READ', utf8Decode(data));\n"
" exit(1);\n" " exit(1);\n"
"}).catch(function(error) {\n" "}).catch(function(error) {\n"
" print('expected error', error);\n" " print('expected error', error);\n"
"});\n"); "});\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -617,20 +617,20 @@ static void _test_file(const tf_test_options_t* options)
static void _test_sign(const tf_test_options_t* options) static void _test_sign(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"'use strict';\n" "'use strict';\n"
"let id = ssb.createIdentity('test');\n" "let id = ssb.createIdentity('test');\n"
"print(id);\n" "print(id);\n"
"let sig = ssb.hmacsha256sign('hello', 'test', id);\n" "let sig = ssb.hmacsha256sign('hello', 'test', id);\n"
"print(sig);\n" "print(sig);\n"
"if (!ssb.hmacsha256verify(id, 'hello', sig)) {\n" "if (!ssb.hmacsha256verify(id, 'hello', sig)) {\n"
" exit(1);\n" " exit(1);\n"
"}\n" "}\n"
"if (ssb.hmacsha256verify(id, 'world', sig)) {\n" "if (ssb.hmacsha256verify(id, 'world', sig)) {\n"
" exit(1);\n" " exit(1);\n"
"}\n" "}\n"
"if (ssb.hmacsha256verify(id, 'hello1', sig)) {\n" "if (ssb.hmacsha256verify(id, 'hello1', sig)) {\n"
" exit(1);\n" " exit(1);\n"
"}\n"); "}\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -646,13 +646,13 @@ static void _test_sign(const tf_test_options_t* options)
static void _test_b64(const tf_test_options_t* options) static void _test_b64(const tf_test_options_t* options)
{ {
_write_file("out/test.js", _write_file("out/test.js",
"'use strict';\n" "'use strict';\n"
"print(base64Encode('hello'));\n" "print(base64Encode('hello'));\n"
"let x = utf8Decode(base64Decode(base64Encode('hello')));\n" "let x = utf8Decode(base64Decode(base64Encode('hello')));\n"
"if (x !== 'hello') {\n" "if (x !== 'hello') {\n"
" print(x);\n" " print(x);\n"
" exit(1);\n" " exit(1);\n"
"}\n"); "}\n");
char command[256]; char command[256];
snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path); snprintf(command, sizeof(command), "%s run --db-path=:memory: -s out/test.js" TEST_ARGS, options->exe_path);
@ -667,7 +667,7 @@ static void _test_b64(const tf_test_options_t* options)
static const char* k_bip39_test_key_base64 = "GO0Lv5BvcuuJJdHrokHoo0PmCDC/XjO/SZ6H+ddq4UvWd/VPW1RJrjd1aCUIfPIojFXrWMb8R54vVerU2TwjdQ==.ed25519"; static const char* k_bip39_test_key_base64 = "GO0Lv5BvcuuJJdHrokHoo0PmCDC/XjO/SZ6H+ddq4UvWd/VPW1RJrjd1aCUIfPIojFXrWMb8R54vVerU2TwjdQ==.ed25519";
static const char* k_bip32_test_key_words = static const char* k_bip32_test_key_words =
"body hair useful camp warm into cause riot two bamboo kick educate dinosaur advice seed type crisp where guilt avocado output rely lunch goddess"; "body hair useful camp warm into cause riot two bamboo kick educate dinosaur advice seed type crisp where guilt avocado output rely lunch goddess";
static void _test_bip39(const tf_test_options_t* options) static void _test_bip39(const tf_test_options_t* options)
{ {

View File

@ -298,8 +298,7 @@ static void _tf_trace_end_tagged(tf_trace_t* trace, void* tag)
} }
char line[1024]; char line[1024];
int p = int p = snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"tid\": %" PRId64 ", \"ts\": %" PRId64 ", \"name\": \"", getpid(), (int64_t)pthread_self(), _trace_ts());
snprintf(line, sizeof(line), "{\"ph\": \"E\", \"pid\": %d, \"tid\": %" PRId64 ", \"ts\": %" PRId64 ", \"name\": \"", getpid(), (int64_t)pthread_self(), _trace_ts());
p += _tf_trace_escape_name(line + p, sizeof(line) - p, name); p += _tf_trace_escape_name(line + p, sizeof(line) - p, name);
p += snprintf(line + p, sizeof(line) - p, "\"},"); p += snprintf(line + p, sizeof(line) - p, "\"},");
p = tf_min(p, tf_countof(line)); p = tf_min(p, tf_countof(line));
@ -327,15 +326,14 @@ char* tf_trace_export(tf_trace_t* trace)
size += snprintf(buffer, k_buffer_size, "{\"displayTimeUnit\": \"ns\",\n\"traceEvents\": [\n"); size += snprintf(buffer, k_buffer_size, "{\"displayTimeUnit\": \"ns\",\n\"traceEvents\": [\n");
if (*trace->process_name) if (*trace->process_name)
{ {
size += snprintf( size += snprintf(buffer + size, k_buffer_size - size, "{\"ph\":\"M\",\"pid\":%d,\"name\":\"process_name\",\"args\":{\"name\":\"%s\"}},\n", getpid(), trace->process_name);
buffer + size, k_buffer_size - size, "{\"ph\":\"M\",\"pid\":%d,\"name\":\"process_name\",\"args\":{\"name\":\"%s\"}},\n", getpid(), trace->process_name);
} }
uv_rwlock_rdlock(&trace->threads_lock); uv_rwlock_rdlock(&trace->threads_lock);
for (int i = 0; i < trace->threads_count; i++) for (int i = 0; i < trace->threads_count; i++)
{ {
tf_trace_thread_t* thread = trace->threads[i]; tf_trace_thread_t* thread = trace->threads[i];
size += snprintf(buffer + size, k_buffer_size - size, "{\"ph\":\"M\",\"pid\":%d,\"tid\":%" PRId64 ",\"name\":\"thread_name\",\"args\":{\"name\":\"%s\"}},\n", size += snprintf(buffer + size, k_buffer_size - size, "{\"ph\":\"M\",\"pid\":%d,\"tid\":%" PRId64 ",\"name\":\"thread_name\",\"args\":{\"name\":\"%s\"}},\n", getpid(),
getpid(), (uint64_t)thread->id, thread->name); (uint64_t)thread->id, thread->name);
} }
uv_rwlock_rdunlock(&trace->threads_lock); uv_rwlock_rdunlock(&trace->threads_lock);
if (begin) if (begin)

View File

@ -273,8 +273,7 @@ static JSValue _util_parseHttpRequest(JSContext* context, JSValueConst this_val,
if (array) if (array)
{ {
int parse_result = int parse_result = phr_parse_request((const char*)array, length, &method, &method_length, &path, &path_length, &minor_version, headers, &header_count, previous_length);
phr_parse_request((const char*)array, length, &method, &method_length, &path, &path_length, &minor_version, headers, &header_count, previous_length);
if (parse_result > 0) if (parse_result > 0)
{ {
result = JS_NewObject(context); result = JS_NewObject(context);