I just decided. Braces on their own lines.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3668 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2021-10-10 21:51:38 +00:00
parent 470814f147
commit 843c53e15e
20 changed files with 2373 additions and 1110 deletions

View File

@ -7,7 +7,8 @@
JSValue _crypt_hashpw(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
JSValue _crypt_gensalt(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
void tf_bcrypt_init(JSContext* context) {
void tf_bcrypt_init(JSContext* context)
{
JSValue global = JS_GetGlobalObject(context);
JSValue bcrypt = JS_NewObject(context);
JS_SetPropertyStr(context, global, "bCrypt", bcrypt);
@ -16,7 +17,8 @@ void tf_bcrypt_init(JSContext* context) {
JS_FreeValue(context, global);
}
JSValue _crypt_hashpw(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _crypt_hashpw(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
const char* key = JS_ToCString(context, argv[0]);
const char* salt = JS_ToCString(context, argv[1]);
char output[7 + 22 + 31 + 1];
@ -27,7 +29,8 @@ JSValue _crypt_hashpw(JSContext* context, JSValueConst this_val, int argc, JSVal
return result;
}
JSValue _crypt_gensalt(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _crypt_gensalt(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
int length;
JS_ToInt32(context, &length, argv[0]);
char buffer[16];

View File

@ -9,7 +9,8 @@
static JSClassID _database_class_id;
static int _database_count;
typedef struct _database_t {
typedef struct _database_t
{
JSContext* context;
JSValue object;
void* task;
@ -26,13 +27,15 @@ static JSValue _database_remove(JSContext* context, JSValueConst this_val, int a
static JSValue _database_get_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue _database_get_like(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
void tf_database_init(JSContext* context, sqlite3* sqlite) {
void tf_database_init(JSContext* context, sqlite3* sqlite)
{
JS_NewClassID(&_database_class_id);
JSClassDef def = {
.class_name = "Database",
.finalizer = &_database_finalizer,
};
if (JS_NewClass(JS_GetRuntime(context), _database_class_id, &def) != 0) {
if (JS_NewClass(JS_GetRuntime(context), _database_class_id, &def) != 0)
{
printf("Failed to register database.\n");
}
@ -44,14 +47,16 @@ void tf_database_init(JSContext* context, sqlite3* sqlite) {
JS_FreeValue(context, global);
}
static JSValue _database_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv, int magic, JSValue* data) {
static JSValue _database_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv, int magic, JSValue* data)
{
++_database_count;
JSValue object = JS_NewObjectClass(context, _database_class_id);
sqlite3* db = NULL;
JS_ToInt64(context, (int64_t*)&db, data[0]);
database_t* database = malloc(sizeof(database_t));
*database = (database_t) {
*database = (database_t)
{
.task = JS_GetContextOpaque(context),
.context = context,
.object = object,
@ -71,26 +76,32 @@ static JSValue _database_create(JSContext* context, JSValueConst this_val, int a
return object;
}
static void _database_finalizer(JSRuntime *runtime, JSValue value) {
static void _database_finalizer(JSRuntime *runtime, JSValue value)
{
database_t* database = JS_GetOpaque(value, _database_class_id);
if (database) {
if (database)
{
free((void*)database->id);
free(database);
}
--_database_count;
}
static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
JSValue entry = JS_UNDEFINED;
database_t* database = JS_GetOpaque(this_val, _database_class_id);
if (database) {
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "SELECT value FROM properties WHERE id = $1 AND key = $2", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(database->db, "SELECT value FROM properties WHERE id = $1 AND key = $2", -1, &statement, NULL) == SQLITE_OK)
{
size_t length;
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 &&
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));
}
JS_FreeCString(context, keyString);
@ -100,11 +111,14 @@ static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc
return entry;
}
JSValue _database_set(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _database_set(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
database_t* database = JS_GetOpaque(this_val, _database_class_id);
if (database) {
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, $2, $3)", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(database->db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, $2, $3)", -1, &statement, NULL) == SQLITE_OK)
{
size_t keyLength;
const char* keyString = JS_ToCStringLen(context, &keyLength, argv[0]);
size_t valueLength;
@ -112,7 +126,8 @@ JSValue _database_set(JSContext* context, JSValueConst this_val, int argc, JSVal
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_step(statement) == SQLITE_OK)
{
}
JS_FreeCString(context, keyString);
JS_FreeCString(context, valueString);
@ -122,16 +137,20 @@ JSValue _database_set(JSContext* context, JSValueConst this_val, int argc, JSVal
return JS_UNDEFINED;
}
JSValue _database_remove(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _database_remove(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
database_t* database = JS_GetOpaque(this_val, _database_class_id);
if (database) {
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "DELETE FROM properties WHERE id = $1 AND key = $2", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(database->db, "DELETE FROM properties WHERE id = $1 AND key = $2", -1, &statement, NULL) == SQLITE_OK)
{
size_t keyLength;
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 &&
sqlite3_step(statement) == SQLITE_OK) {
sqlite3_step(statement) == SQLITE_OK)
{
}
JS_FreeCString(context, keyString);
sqlite3_finalize(statement);
@ -140,16 +159,21 @@ JSValue _database_remove(JSContext* context, JSValueConst this_val, int argc, JS
return JS_UNDEFINED;
}
JSValue _database_get_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _database_get_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
JSValue array = JS_UNDEFINED;
database_t* database = JS_GetOpaque(this_val, _database_class_id);
if (database) {
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "SELECT key, value FROM properties WHERE id = $1", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK) {
if (sqlite3_prepare(database->db, "SELECT key, value FROM properties WHERE id = $1", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK)
{
array = JS_NewArray(context);
uint32_t index = 0;
while (sqlite3_step(statement) == SQLITE_ROW) {
while (sqlite3_step(statement) == SQLITE_ROW)
{
JS_SetPropertyUint32(context, array, index++, JS_NewStringLen(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0)));
}
}
@ -159,17 +183,22 @@ JSValue _database_get_all(JSContext* context, JSValueConst this_val, int argc, J
return array;
}
JSValue _database_get_like(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _database_get_like(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
JSValue result = JS_UNDEFINED;
database_t* database = JS_GetOpaque(this_val, _database_class_id);
if (database) {
if (database)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(database->db, "SELECT key, value FROM properties WHERE id = ? AND KEY LIKE ?", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(database->db, "SELECT key, value FROM properties WHERE id = ? AND KEY LIKE ?", -1, &statement, NULL) == SQLITE_OK)
{
const char* pattern = JS_ToCString(context, argv[0]);
if (sqlite3_bind_text(statement, 1, database->id, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 2, pattern, -1, NULL) == SQLITE_OK) {
sqlite3_bind_text(statement, 2, pattern, -1, NULL) == SQLITE_OK)
{
result = JS_NewObject(context);
while (sqlite3_step(statement) == SQLITE_ROW) {
while (sqlite3_step(statement) == SQLITE_ROW)
{
JS_SetPropertyStr(
context,
result,

View File

@ -31,7 +31,8 @@ typedef struct file_stat_t {
uv_fs_t _request;
} file_stat_t;
void tf_file_init(JSContext* context) {
void tf_file_init(JSContext* context)
{
JSValue global = JS_GetGlobalObject(context);
JSValue file = JS_NewObject(context);
JS_SetPropertyStr(context, global, "File", file);
@ -106,7 +107,8 @@ static void _file_read_open_callback(uv_fs_t* req)
}
}
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
void* task = JS_GetContextOpaque(context);
const char* file_name = JS_ToCString(context, argv[0]);
@ -125,19 +127,24 @@ static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int ar
return tf_task_get_promise(task, promise);
}
static JSValue _file_write_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _file_write_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
JSValue result = JS_NULL;
const char* fileName = JS_ToCString(context, argv[0]);
FILE* file = fopen(fileName, "wb");
JS_FreeCString(context, fileName);
if (file) {
if (file)
{
size_t size;
uint8_t* buffer = tf_try_get_array_buffer(context, &size, argv[1]);
if (buffer) {
if (buffer)
{
int written = fwrite((const char*)buffer, 1, size, file);
result = JS_NewInt32(context, (size_t)written == size ? 0 : written);
} else {
}
else
{
const char* data = JS_ToCStringLen(context, &size, argv[1]);
int written = fwrite((const char*)data, 1, size, file);
result = JS_NewInt32(context, (size_t)written == size ? 0 : written);
@ -148,7 +155,8 @@ static JSValue _file_write_file(JSContext* context, JSValueConst this_val, int a
return result;
}
static JSValue _file_rename_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _file_rename_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
void* task = JS_GetContextOpaque(context);
const char* oldName = JS_ToCString(context, argv[0]);
const char* newName = JS_ToCString(context, argv[1]);
@ -159,7 +167,8 @@ static JSValue _file_rename_file(JSContext* context, JSValueConst this_val, int
return JS_NewInt32(context, result);
}
static JSValue _file_unlink_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _file_unlink_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
void* task = JS_GetContextOpaque(context);
const char* fileName = JS_ToCString(context, argv[0]);
uv_fs_t req;
@ -168,7 +177,8 @@ static JSValue _file_unlink_file(JSContext* context, JSValueConst this_val, int
return JS_NewInt32(context, result);
}
static JSValue _file_read_directory(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _file_read_directory(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
const char* directory = JS_ToCString(context, argv[0]);
JSValue array = JS_NewArray(context);
@ -177,7 +187,8 @@ static JSValue _file_read_directory(JSContext* context, JSValueConst this_val, i
std::string pattern = directory;
pattern += "\\*";
HANDLE handle = FindFirstFile(pattern.c_str(), &find);
if (handle != INVALID_HANDLE_VALUE) {
if (handle != INVALID_HANDLE_VALUE)
{
int index = 0;
do {
JS_SetPropertyUint32(context, array, index++, JS_NewString(context, find.cFileName));
@ -186,10 +197,12 @@ static JSValue _file_read_directory(JSContext* context, JSValueConst this_val, i
}
#else
DIR* dir = opendir(directory);
if (dir) {
if (dir)
{
uint32_t index = 0;
struct dirent* entry = readdir(dir);
while (entry) {
while (entry)
{
JS_SetPropertyUint32(context, array, index++, JS_NewString(context, entry->d_name));
entry = readdir(dir);
}
@ -201,7 +214,8 @@ static JSValue _file_read_directory(JSContext* context, JSValueConst this_val, i
return array;
}
JSValue _file_make_directory(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _file_make_directory(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
void* task = JS_GetContextOpaque(context);
const char* directory = JS_ToCString(context, argv[0]);
@ -211,7 +225,8 @@ JSValue _file_make_directory(JSContext* context, JSValueConst this_val, int argc
return JS_NewInt32(context, result);
}
JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
void* task = JS_GetContextOpaque(context);
const char* path = JS_ToCString(context, argv[0]);
promiseid_t promise = tf_task_allocate_promise(task);
@ -223,7 +238,8 @@ JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueC
data->_context = context;
int result = uv_fs_stat(tf_task_get_loop(task), &data->_request, path, _file_on_stat_complete);
if (result) {
if (result)
{
tf_task_reject_promise(task, promise, JS_NewInt32(context, result));
free(data);
}
@ -231,17 +247,22 @@ JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueC
return tf_task_get_promise(task, promise);
}
static double _time_spec_to_double(const uv_timespec_t* time_spec) {
static double _time_spec_to_double(const uv_timespec_t* time_spec)
{
return time_spec->tv_sec + (double)(time_spec->tv_nsec) / 1e9;
}
static void _file_on_stat_complete(uv_fs_t* request) {
static void _file_on_stat_complete(uv_fs_t* request)
{
file_stat_t* data = (file_stat_t*)(request->data);
JSContext* context = data->_context;
if (request->result) {
if (request->result)
{
tf_task_reject_promise(data->_task, data->_promise, JS_NewInt32(context, request->result));
} else {
}
else
{
JSValue result = JS_NewObject(context);
JS_SetPropertyStr(context, result, "mtime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_mtim)));
JS_SetPropertyStr(context, result, "ctime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_ctim)));

View File

@ -29,7 +29,8 @@
_xopt_ctx = xopt_context((name), (options), ((flags) ^ XOPT_CTX_POSIXMEHARDER), (err_ptr)); \
if (*(err_ptr)) break; \
*extrac_ptr = xopt_parse(_xopt_ctx, (argc), (argv), (config_ptr), (extrav_ptr), (err_ptr)); \
if ((config_ptr)->help) { \
if ((config_ptr)->help) \
{ \
xoptAutohelpOptions __xopt_autohelp_opts; \
__xopt_autohelp_opts.usage = (autohelp_usage); \
__xopt_autohelp_opts.prefix = (autohelp_prefix); \
@ -91,24 +92,29 @@ void shedPrivileges()
// RLIMIT_SIGPENDING
// RLIMIT_STACK
if (setrlimit(RLIMIT_FSIZE, &zeroLimit) != 0) {
if (setrlimit(RLIMIT_FSIZE, &zeroLimit) != 0)
{
perror("setrlimit(RLIMIT_FSIZE, {0, 0})");
exit(-1);
}
if (setrlimit(RLIMIT_NOFILE, &zeroLimit) != 0) {
if (setrlimit(RLIMIT_NOFILE, &zeroLimit) != 0)
{
perror("setrlimit(RLIMIT_NOFILE, {0, 0})");
exit(-1);
}
if (setrlimit(RLIMIT_NPROC, &zeroLimit) != 0) {
if (setrlimit(RLIMIT_NPROC, &zeroLimit) != 0)
{
perror("setrlimit(RLIMIT_NPROC, {0, 0})");
exit(-1);
}
#if !defined (__MACH__)
if (setrlimit(RLIMIT_LOCKS, &zeroLimit) != 0) {
if (setrlimit(RLIMIT_LOCKS, &zeroLimit) != 0)
{
perror("setrlimit(RLIMIT_LOCKS, {0, 0})");
exit(-1);
}
if (setrlimit(RLIMIT_MSGQUEUE, &zeroLimit) != 0) {
if (setrlimit(RLIMIT_MSGQUEUE, &zeroLimit) != 0)
{
perror("setrlimit(RLIMIT_MSGQUEUE, {0, 0})");
exit(-1);
}
@ -134,10 +140,12 @@ static int _tf_command_test(const char* file, int argc, char* argv[])
int extra_count = 0;
const char *err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "test [options]", "options:", NULL, 15);
if (extras) {
if (extras)
{
free((void*)extras);
}
if (err) {
if (err)
{
fprintf(stderr, "Error: %s\n", err);
return 2;
}
@ -150,7 +158,8 @@ static int _tf_command_test(const char* file, int argc, char* argv[])
tf_tests(&test_options);
return 0;
xopt_help:
if (extras) {
if (extras)
{
free((void*)extras);
}
return 1;
@ -177,40 +186,50 @@ static int _tf_command_import(const char* file, int argc, char* argv[])
const char *err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "import [options] [paths] ...", "options:", NULL, 15);
if (err) {
if (err)
{
fprintf(stderr, "Error: %s\n", err);
if (extras) {
if (extras)
{
free((void*)extras);
}
return 2;
}
sqlite3* db = NULL;
if (args.db_path) {
if (args.db_path)
{
sqlite3_open(args.db_path, &db);
}
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db, NULL);
if (extra_count) {
for (int i = 0; i < extra_count; i++) {
if (extra_count)
{
for (int i = 0; i < extra_count; i++)
{
printf("Importing %s...\n", extras[i]);
tf_ssb_import(ssb, args.user, extras[i]);
}
} else {
}
else
{
printf("Importing %s...\n", "apps");
tf_ssb_import(ssb, args.user, "apps");
}
tf_ssb_destroy(ssb);
if (db) {
if (db)
{
sqlite3_close(db);
}
if (extras) {
if (extras)
{
free((void*)extras);
}
return 0;
xopt_help:
if (extras) {
if (extras)
{
free((void*)extras);
}
return 1;
@ -233,38 +252,47 @@ static int _tf_command_export(const char* file, int argc, char* argv[])
const char *err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "export [options] [paths] ...", "options:", NULL, 15);
if (err) {
if (err)
{
fprintf(stderr, "Error: %s\n", err);
if (extras) {
if (extras)
{
free((void*)extras);
}
return 2;
}
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, NULL, NULL);
if (extra_count) {
for (int i = 0; i < extra_count; i++) {
if (extra_count)
{
for (int i = 0; i < extra_count; i++)
{
printf("Exporting %s...\n", extras[i]);
tf_ssb_export(ssb, extras[i]);
}
} else {
}
else
{
const char* k_export[] = {
"/~cory/index",
"/~cory/docs",
};
for (int i = 0; i < _countof(k_export); i++) {
for (int i = 0; i < _countof(k_export); i++)
{
printf("Exporting %s...\n", k_export[i]);
tf_ssb_export(ssb, k_export[i]);
}
}
tf_ssb_destroy(ssb);
if (extras) {
if (extras)
{
free((void*)extras);
}
return 0;
xopt_help:
if (extras) {
if (extras)
{
free((void*)extras);
}
return 1;
@ -304,14 +332,17 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
const char *err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "run [options] [paths] ...", "options:", NULL, 15);
if (err) {
if (err)
{
fprintf(stderr, "Error: %s\n", err);
if (extras) {
if (extras)
{
free((void*)extras);
}
return 2;
}
if (extras) {
if (extras)
{
free((void*)extras);
}
@ -340,7 +371,8 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
return result;
xopt_help:
if (extras) {
if (extras)
{
free((void*)extras);
}
return 1;
@ -364,14 +396,17 @@ static int _tf_command_sandbox(const char* file, int argc, char* argv[])
const char *err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "sandbox [options]", "options:", NULL, 15);
if (err) {
if (err)
{
fprintf(stderr, "Error: %s\n", err);
if (extras) {
if (extras)
{
free((void*)extras);
}
return 2;
}
if (extras) {
if (extras)
{
free((void*)extras);
}
@ -387,7 +422,8 @@ static int _tf_command_sandbox(const char* file, int argc, char* argv[])
return 0;
xopt_help:
if (extras) {
if (extras)
{
free((void*)extras);
}
return 1;
@ -411,10 +447,12 @@ static int _tf_command_post(const char* file, int argc, char* argv[])
int extra_count = 0;
const char *err = NULL;
XOPT_PARSE(file, XOPT_CTX_KEEPFIRST, options, &args, argc, (const char**)argv, &extra_count, &extras, &err, stderr, "post [options]", "options:", NULL, 15);
if (extras) {
if (extras)
{
free((void*)extras);
}
if (err) {
if (err)
{
fprintf(stderr, "Error: %s\n", err);
return 2;
}
@ -426,7 +464,8 @@ static int _tf_command_post(const char* file, int argc, char* argv[])
return 0;
xopt_help:
if (extras) {
if (extras)
{
free((void*)extras);
}
return 1;
@ -436,7 +475,8 @@ static int _tf_command_usage(const char* file, int argc, char* argv[])
{
printf("Usage: %s command [command-options]\n", file);
printf("commands:\n");
for (int i = 0; i < _countof(k_commands); i++) {
for (int i = 0; i < _countof(k_commands); i++)
{
printf(" %s - %s\n", k_commands[i].name, k_commands[i].description);
}
return 0;
@ -449,15 +489,19 @@ int main(int argc, char* argv[])
tf_taskstub_startup();
#if !defined (_WIN32)
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
{
perror("signal");
}
#endif
if (argc >= 2) {
for (int i = 0; i < _countof(k_commands); i++) {
if (argc >= 2)
{
for (int i = 0; i < _countof(k_commands); i++)
{
const command_t* command = &k_commands[i];
if (strcmp(argv[1], command->name) == 0) {
if (strcmp(argv[1], command->name) == 0)
{
return command->callback(argv[0], argc - 2, argv + 2);
}
}

View File

@ -15,84 +15,106 @@ typedef struct _tf_packetstream_t {
bool destroyed;
} tf_packetstream_t;
tf_packetstream_t* tf_packetstream_create() {
tf_packetstream_t* tf_packetstream_create()
{
tf_packetstream_t* impl = malloc(sizeof(tf_packetstream_t));
*impl = (tf_packetstream_t) { 0 };
return impl;
}
void tf_packetstream_destroy(tf_packetstream_t* stream) {
void tf_packetstream_destroy(tf_packetstream_t* stream)
{
stream->onreceive = NULL;
stream->onreceive_user_data = NULL;
stream->destroyed = true;
if (stream->stream.data) {
if (stream->stream.data)
{
tf_packetstream_close(stream);
} else {
}
else
{
free(stream);
}
}
static void _packetstream_allocate(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buffer) {
static void _packetstream_allocate(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buffer)
{
buffer->base = malloc(suggested_size);
buffer->len = suggested_size;
}
static void _packetstream_process_messages(tf_packetstream_t* stream) {
static void _packetstream_process_messages(tf_packetstream_t* stream)
{
int packet_type = 0;
size_t length = 0;
while (stream->buffer_size >= sizeof(packet_type) + sizeof(length)) {
while (stream->buffer_size >= sizeof(packet_type) + sizeof(length))
{
memcpy(&packet_type, stream->buffer, sizeof(packet_type));
memcpy(&length, stream->buffer + sizeof(packet_type), sizeof(length));
if (stream->buffer_size >= sizeof(packet_type) + sizeof(length) + length) {
if (stream->onreceive) {
if (stream->buffer_size >= sizeof(packet_type) + sizeof(length) + length)
{
if (stream->onreceive)
{
stream->onreceive(packet_type, stream->buffer + sizeof(length) + sizeof(packet_type), length, stream->onreceive_user_data);
}
size_t consumed = sizeof(length) + sizeof(packet_type) + length;
memmove(stream->buffer, stream->buffer + consumed, stream->buffer_size - consumed);
stream->buffer_size -= consumed;
stream->buffer = realloc(stream->buffer, stream->buffer_size);
} else {
}
else
{
break;
}
}
}
static void _packetstream_on_read(uv_stream_t* handle, ssize_t count, const uv_buf_t* buffer) {
static void _packetstream_on_read(uv_stream_t* handle, ssize_t count, const uv_buf_t* buffer)
{
tf_packetstream_t* stream = handle->data;
if (count >= 0) {
if (count > 0) {
if (count >= 0)
{
if (count > 0)
{
char* new_buffer = realloc(stream->buffer, stream->buffer_size + count);
if (new_buffer) {
if (new_buffer)
{
memcpy(new_buffer + stream->buffer_size, buffer->base, count);
stream->buffer = new_buffer;
stream->buffer_size += count;
}
_packetstream_process_messages(stream);
}
} else {
}
else
{
tf_packetstream_close(stream);
}
free(buffer->base);
}
void tf_packetstream_start(tf_packetstream_t* stream) {
void tf_packetstream_start(tf_packetstream_t* stream)
{
stream->stream.data = stream;
uv_read_start((uv_stream_t*)&stream->stream, _packetstream_allocate, _packetstream_on_read);
}
static void _packetstream_on_write(uv_write_t* request, int status) {
static void _packetstream_on_write(uv_write_t* request, int status)
{
free(request);
}
void tf_packetstream_send(tf_packetstream_t* stream, int packet_type, char* begin, size_t length) {
void tf_packetstream_send(tf_packetstream_t* stream, int packet_type, char* begin, size_t length)
{
size_t buffer_length = sizeof(uv_write_t) + sizeof(packet_type) + sizeof(length) + length;
uv_write_t* request = malloc(buffer_length);
memset(request, 0, sizeof(uv_write_t));
char* buffer = (char*)(request + 1);
memcpy(buffer, &packet_type, sizeof(packet_type));
memcpy(buffer + sizeof(packet_type), &length, sizeof(length));
if (length) {
if (length)
{
memcpy(buffer + sizeof(packet_type) + sizeof(length), begin, length);
}
uv_buf_t write_buffer;
@ -101,7 +123,8 @@ void tf_packetstream_send(tf_packetstream_t* stream, int packet_type, char* begi
uv_write(request, (uv_stream_t*)&stream->stream, &write_buffer, 1, _packetstream_on_write);
}
void tf_packetstream_set_on_receive(tf_packetstream_t* stream, tf_packetstream_onreceive_t* callback, void* user_data) {
void tf_packetstream_set_on_receive(tf_packetstream_t* stream, tf_packetstream_onreceive_t* callback, void* user_data)
{
stream->onreceive = callback;
stream->onreceive_user_data = user_data;
}
@ -110,17 +133,21 @@ static void _tf_packetstream_handle_closed(uv_handle_t* handle)
{
tf_packetstream_t* packetstream = handle->data;
handle->data = NULL;
if (packetstream->destroyed) {
if (packetstream->destroyed)
{
free(packetstream);
}
}
void tf_packetstream_close(tf_packetstream_t* stream) {
if (stream->stream.data && !uv_is_closing((uv_handle_t*)&stream->stream)) {
void tf_packetstream_close(tf_packetstream_t* stream)
{
if (stream->stream.data && !uv_is_closing((uv_handle_t*)&stream->stream))
{
uv_close((uv_handle_t*)&stream->stream, _tf_packetstream_handle_closed);
}
}
uv_pipe_t* tf_packetstream_get_pipe(tf_packetstream_t* stream) {
uv_pipe_t* tf_packetstream_get_pipe(tf_packetstream_t* stream)
{
return &stream->stream;
}

View File

@ -48,7 +48,8 @@ static int32_t _serialize_readInt32(const char** buffer, size_t* size);
static int64_t _serialize_readInt64(const char** buffer, size_t* size);
static double _serialize_readDouble(const char** buffer, size_t* size);
void tf_serialize_store(tf_task_t* task, tf_taskstub_t* to, void** out_buffer, size_t* out_size, JSValue value) {
void tf_serialize_store(tf_task_t* task, tf_taskstub_t* to, void** out_buffer, size_t* out_size, JSValue value)
{
buffer_t tmp = { 0 };
_serialize_store(task, to, &tmp, value);
tmp.data = realloc(tmp.data, tmp.size);
@ -56,12 +57,15 @@ void tf_serialize_store(tf_task_t* task, tf_taskstub_t* to, void** out_buffer, s
*out_size = tmp.size;
}
JSValue tf_serialize_load(tf_task_t* task, tf_taskstub_t* from, const char* buffer, size_t size) {
JSValue tf_serialize_load(tf_task_t* task, tf_taskstub_t* from, const char* buffer, size_t size)
{
return _serialize_load(task, from, buffer, size);
}
static void _buffer_append(buffer_t* buffer, const void* data, size_t size) {
if (buffer->capacity < buffer->size + size) {
static void _buffer_append(buffer_t* buffer, const void* data, size_t size)
{
if (buffer->capacity < buffer->size + size)
{
size_t new_capacity = (size + buffer->capacity) * 2;
buffer->data = realloc(buffer->data, new_capacity);
buffer->capacity = new_capacity;
@ -70,54 +74,64 @@ static void _buffer_append(buffer_t* buffer, const void* data, size_t size) {
buffer->size += size;
}
void _serialize_writeInt8(buffer_t* buffer, int8_t value) {
void _serialize_writeInt8(buffer_t* buffer, int8_t value)
{
_buffer_append(buffer, &value, sizeof(value));
}
void _serialize_writeInt32(buffer_t* buffer, int32_t value) {
void _serialize_writeInt32(buffer_t* buffer, int32_t value)
{
_buffer_append(buffer, &value, sizeof(value));
}
void _serialize_writeInt64(buffer_t* buffer, int64_t value) {
void _serialize_writeInt64(buffer_t* buffer, int64_t value)
{
_buffer_append(buffer, &value, sizeof(value));
}
void _serialize_writeDouble(buffer_t* buffer, double value) {
void _serialize_writeDouble(buffer_t* buffer, double value)
{
_buffer_append(buffer, &value, sizeof(value));
}
static void _serialize_read(const char** buffer, size_t* size, void* target, size_t target_size) {
static void _serialize_read(const char** buffer, size_t* size, void* target, size_t target_size)
{
assert(*size >= target_size);
memcpy(target, *buffer, target_size);
*buffer += target_size;
*size -= target_size;
}
static int8_t _serialize_readInt8(const char** buffer, size_t* size) {
static int8_t _serialize_readInt8(const char** buffer, size_t* size)
{
int8_t result;
_serialize_read(buffer, size, &result, sizeof(result));
return result;
}
int32_t _serialize_readInt32(const char** buffer, size_t* size) {
int32_t _serialize_readInt32(const char** buffer, size_t* size)
{
int32_t result;
_serialize_read(buffer, size, &result, sizeof(result));
return result;
}
int64_t _serialize_readInt64(const char** buffer, size_t* size) {
int64_t _serialize_readInt64(const char** buffer, size_t* size)
{
int64_t result;
_serialize_read(buffer, size, &result, sizeof(result));
return result;
}
double _serialize_readDouble(const char** buffer, size_t* size) {
double _serialize_readDouble(const char** buffer, size_t* size)
{
double result;
_serialize_read(buffer, size, &result, sizeof(result));
return result;
}
static bool _serialize_store(tf_task_t* task, tf_taskstub_t* to, buffer_t* buffer, JSValue value) {
static bool _serialize_store(tf_task_t* task, tf_taskstub_t* to, buffer_t* buffer, JSValue value)
{
return _serialize_storeInternal(task, to, buffer, value, 0);
}
@ -129,16 +143,25 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
size_t element_size;
JSValue typed;
uint8_t* bytes;
if (JS_IsUndefined(value)) {
if (JS_IsUndefined(value))
{
_serialize_writeInt32(buffer, kUndefined);
} else if (JS_IsUninitialized(value)) {
}
else if (JS_IsUninitialized(value))
{
_serialize_writeInt32(buffer, kUninitialized);
} else if (JS_IsNull(value)) {
}
else if (JS_IsNull(value))
{
_serialize_writeInt32(buffer, kNull);
} else if (JS_IsBool(value)) {
}
else if (JS_IsBool(value))
{
_serialize_writeInt32(buffer, kBoolean);
_serialize_writeInt8(buffer, JS_ToBool(tf_task_get_context(task), value) ? 1 : 0);
} else if (JS_IsNumber(value)) {
}
else if (JS_IsNumber(value))
{
int64_t result = 0;
if (JS_ToInt64(tf_task_get_context(task), &result, value) == 0)
{
@ -149,7 +172,9 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
{
fprintf(stderr, "Unable to store integer.\n");
}
} else if (JS_IsNumber(value)) {
}
else if (JS_IsNumber(value))
{
double result = 0.0;
if (JS_ToFloat64(tf_task_get_context(task), &result, value) == 0)
{
@ -160,68 +185,93 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
{
fprintf(stderr, "Unable to store number.\n");
}
} else if (JS_IsString(value)) {
}
else if (JS_IsString(value))
{
size_t len = 0;
const char* result = JS_ToCStringLen(tf_task_get_context(task), &len, value);
_serialize_writeInt32(buffer, kString);
_serialize_writeInt32(buffer, (int32_t)len);
_buffer_append(buffer, result, len);
JS_FreeCString(tf_task_get_context(task), result);
} else if ((bytes = tf_try_get_array_buffer(tf_task_get_context(task), &size, value)) != 0) {
}
else if ((bytes = tf_try_get_array_buffer(tf_task_get_context(task), &size, value)) != 0)
{
_serialize_writeInt32(buffer, kArrayBuffer);
_serialize_writeInt32(buffer, (int32_t)size);
_buffer_append(buffer, bytes, size);
} else if (!JS_IsException((typed = tf_try_get_typed_array_buffer(tf_task_get_context(task), value, &offset, &size, &element_size)))) {
}
else if (!JS_IsException((typed = tf_try_get_typed_array_buffer(tf_task_get_context(task), value, &offset, &size, &element_size))))
{
size_t total_size;
uint8_t* bytes = tf_try_get_array_buffer(tf_task_get_context(task), &total_size, typed);
_serialize_writeInt32(buffer, kArrayBuffer);
_serialize_writeInt32(buffer, (int32_t)size);
_buffer_append(buffer, bytes, size);
} else if (JS_IsArray(tf_task_get_context(task), value)) {
}
else if (JS_IsArray(tf_task_get_context(task), value))
{
_serialize_writeInt32(buffer, kArray);
JSValue length_val = JS_GetPropertyStr(tf_task_get_context(task), value, "length");
int length;
if (JS_ToInt32(tf_task_get_context(task), &length, length_val) == 0) {
if (JS_ToInt32(tf_task_get_context(task), &length, length_val) == 0)
{
_serialize_writeInt32(buffer, length);
for (int i = 0; i < length; ++i) {
for (int i = 0; i < length; ++i)
{
_serialize_storeInternal(task, to, buffer, JS_GetPropertyUint32(tf_task_get_context(task), value, i), depth + 1);
}
} else {
}
else
{
_serialize_writeInt32(buffer, 0);
}
} else if (JS_IsFunction(tf_task_get_context(task), value)) {
}
else if (JS_IsFunction(tf_task_get_context(task), value))
{
_serialize_writeInt32(buffer, kFunction);
exportid_t exportId = tf_task_export_function(task, to, value);
_serialize_writeInt32(buffer, exportId);
} else if (JS_IsException(value)) {
}
else if (JS_IsException(value))
{
JSValue exception = JS_GetException(context);
JSValue error = JS_NewObject(context);
JSValue message = JS_GetPropertyStr(context, exception, "message");
if (!JS_IsException(message)) {
if (!JS_IsException(message))
{
JS_SetPropertyStr(context, error, "message", message);
} else {
}
else
{
JS_FreeValue(context, message);
}
if (JS_IsError(context, exception)) {
if (JS_IsError(context, exception))
{
JSValue stack = JS_GetPropertyStr(context, exception, "stack");
if (!JS_IsUndefined(stack)) {
if (!JS_IsUndefined(stack))
{
JS_SetPropertyStr(context, error, "stack", JS_DupValue(context, stack));
}
}
_serialize_writeInt32(buffer, kException);
_serialize_storeInternal(task, to, buffer, error, depth + 1);
JS_FreeValue(context, error);
} else if (JS_IsError(tf_task_get_context(task), value)) {
}
else if (JS_IsError(tf_task_get_context(task), value))
{
_serialize_writeInt32(buffer, kError);
JSPropertyEnum* ptab;
uint32_t plen;
JS_GetOwnPropertyNames(tf_task_get_context(task), &ptab, &plen, value, JS_GPN_STRING_MASK);
_serialize_writeInt32(buffer, plen);
for (uint32_t i = 0; i < plen; ++i) {
for (uint32_t i = 0; i < plen; ++i)
{
JSValue key = JS_AtomToString(tf_task_get_context(task), ptab[i].atom);
JSPropertyDescriptor desc;
JSValue key_value = JS_NULL;
if (JS_GetOwnProperty(tf_task_get_context(task), &desc, value, ptab[i].atom) == 1) {
if (JS_GetOwnProperty(tf_task_get_context(task), &desc, value, ptab[i].atom) == 1)
{
key_value = desc.value;
}
_serialize_storeInternal(task, to, buffer, key, depth + 1);
@ -229,21 +279,26 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
JS_FreeValue(tf_task_get_context(task), key);
JS_FreeValue(tf_task_get_context(task), key_value);
}
for (uint32_t i = 0; i < plen; ++i) {
for (uint32_t i = 0; i < plen; ++i)
{
JS_FreeAtom(tf_task_get_context(task), ptab[i].atom);
}
js_free(tf_task_get_context(task), ptab);
} else if (JS_IsObject(value)) {
}
else if (JS_IsObject(value))
{
_serialize_writeInt32(buffer, kObject);
JSPropertyEnum* ptab;
uint32_t plen;
JS_GetOwnPropertyNames(tf_task_get_context(task), &ptab, &plen, value, JS_GPN_STRING_MASK);
_serialize_writeInt32(buffer, plen);
for (uint32_t i = 0; i < plen; ++i) {
for (uint32_t i = 0; i < plen; ++i)
{
JSValue key = JS_AtomToString(tf_task_get_context(task), ptab[i].atom);
JSPropertyDescriptor desc;
JSValue key_value = JS_NULL;
if (JS_GetOwnProperty(tf_task_get_context(task), &desc, value, ptab[i].atom) == 1) {
if (JS_GetOwnProperty(tf_task_get_context(task), &desc, value, ptab[i].atom) == 1)
{
key_value = desc.value;
}
_serialize_storeInternal(task, to, buffer, key, depth + 1);
@ -251,11 +306,14 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
JS_FreeValue(tf_task_get_context(task), key);
JS_FreeValue(tf_task_get_context(task), key_value);
}
for (uint32_t i = 0; i < plen; ++i) {
for (uint32_t i = 0; i < plen; ++i)
{
JS_FreeAtom(tf_task_get_context(task), ptab[i].atom);
}
js_free(tf_task_get_context(task), ptab);
} else {
}
else
{
fprintf(stderr, "Unknown JSValue type: %d.\n", JS_VALUE_GET_TAG(value));
abort();
}
@ -263,18 +321,24 @@ static bool _serialize_storeInternal(tf_task_t* task, tf_taskstub_t* to, buffer_
return true;
}
static JSValue _serialize_load(tf_task_t* task, tf_taskstub_t* from, const char* buffer, size_t size) {
static JSValue _serialize_load(tf_task_t* task, tf_taskstub_t* from, const char* buffer, size_t size)
{
return _serialize_loadInternal(task, from, &buffer, &size, 0);
}
static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, const char** buffer, size_t* size, int depth) {
if (*size < sizeof(size)) {
static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, const char** buffer, size_t* size, int depth)
{
if (*size < sizeof(size))
{
return JS_UNDEFINED;
} else {
}
else
{
int32_t type = _serialize_readInt32(buffer, size);
JSValue result = JS_UNDEFINED;
switch (type) {
switch (type)
{
case kUndefined:
result = JS_UNDEFINED;
break;
@ -316,7 +380,8 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
{
int32_t length = _serialize_readInt32(buffer, size);
result = JS_NewArray(tf_task_get_context(task));
for (int i = 0; i < length; ++i) {
for (int i = 0; i < length; ++i)
{
JS_SetPropertyUint32(tf_task_get_context(task), result, i, _serialize_loadInternal(task, from, buffer, size, depth + 1));
}
}
@ -332,7 +397,8 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
_serialize_readInt32(buffer, size);
JSValue error = JS_NewError(tf_task_get_context(task));
int32_t length = _serialize_readInt32(buffer, size);
for (int i = 0; i < length; ++i) {
for (int i = 0; i < length; ++i)
{
JSValue key = _serialize_loadInternal(task, from, buffer, size, depth + 1);
JSValue value = _serialize_loadInternal(task, from, buffer, size, depth + 1);
const char* key_str = JS_ToCString(tf_task_get_context(task), key);
@ -348,7 +414,8 @@ static JSValue _serialize_loadInternal(tf_task_t* task, tf_taskstub_t* from, con
{
int32_t length = _serialize_readInt32(buffer, size);
result = JS_NewObject(tf_task_get_context(task));
for (int i = 0; i < length; ++i) {
for (int i = 0; i < length; ++i)
{
JSValue key = _serialize_loadInternal(task, from, buffer, size, depth + 1);
JSValue value = _serialize_loadInternal(task, from, buffer, size, depth + 1);
const char* key_str = JS_ToCString(tf_task_get_context(task), key);

View File

@ -86,23 +86,27 @@ private:
};
*/
JSValue tf_socket_init(JSContext* context) {
JSValue tf_socket_init(JSContext* context)
{
JS_NewClassID(&_classId);
JSClassDef def = {
.class_name = "Socket",
.finalizer = &_socket_finalizer,
};
if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0) {
if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0)
{
fprintf(stderr, "Failed to register Socket.\n");
}
return JS_NewCFunction2(context, _socket_create, "Socket", 0, JS_CFUNC_constructor, 0);
}
int tf_socket_get_count() {
int tf_socket_get_count()
{
return _count;
}
int tf_socket_get_open_count() {
int tf_socket_get_open_count()
{
return _open_count;
}
@ -112,7 +116,8 @@ typedef struct _socket_resolve_data_t {
promiseid_t promise;
} socket_resolve_data_t;
socket_t* _socket_create_internal(JSContext* context) {
socket_t* _socket_create_internal(JSContext* context)
{
socket_t* socket = malloc(sizeof(socket_t));
memset(socket, 0, sizeof(*socket));
@ -165,23 +170,28 @@ socket_t* _socket_create_internal(JSContext* context) {
return socket;
}
JSValue _socket_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
return _socket_create_internal(context)->_object;
}
void _socket_finalizer(JSRuntime *runtime, JSValue value) {
void _socket_finalizer(JSRuntime *runtime, JSValue value)
{
socket_t* socket = JS_GetOpaque(value, _classId);
--_count;
free(socket);
}
void _socket_close_internal(socket_t* socket) {
if (!uv_is_closing((uv_handle_t*)&socket->_socket)) {
void _socket_close_internal(socket_t* socket)
{
if (!uv_is_closing((uv_handle_t*)&socket->_socket))
{
JS_FreeValue(tf_task_get_context(socket->_task), socket->_onRead);
socket->_onRead = JS_UNDEFINED;
JS_FreeValue(tf_task_get_context(socket->_task), socket->_onError);
socket->_onError = JS_UNDEFINED;
if (socket->_tls) {
if (socket->_tls)
{
tf_tls_session_destroy(socket->_tls);
socket->_tls = NULL;
}
@ -189,82 +199,110 @@ void _socket_close_internal(socket_t* socket) {
}
}
void _socket_reportError(socket_t* socket, const char* error) {
if (JS_IsFunction(tf_task_get_context(socket->_task),socket-> _onError)) {
void _socket_reportError(socket_t* socket, const char* error)
{
if (JS_IsFunction(tf_task_get_context(socket->_task),socket-> _onError))
{
JSValue exception = JS_ThrowInternalError(tf_task_get_context(socket->_task), "%s", error);
JSValue result = JS_Call(tf_task_get_context(socket->_task), socket->_onError, socket->_object, 1, &exception);
if (JS_IsException(result)) {
if (JS_IsException(result))
{
printf("Socket error.\n");
js_std_dump_error(tf_task_get_context(socket->_task));
}
tf_task_run_jobs(socket->_task);
JS_FreeValue(tf_task_get_context(socket->_task), exception);
JS_FreeValue(tf_task_get_context(socket->_task), result);
} else {
}
else
{
fprintf(stderr, "Socket::reportError: %s\n", error);
}
}
void _socket_reportTlsErrors(socket_t* socket) {
void _socket_reportTlsErrors(socket_t* socket)
{
char buffer[4096];
while (socket->_tls && tf_tls_session_get_error(socket->_tls, buffer, sizeof(buffer))) {
while (socket->_tls && tf_tls_session_get_error(socket->_tls, buffer, sizeof(buffer)))
{
_socket_reportError(socket, buffer);
}
}
JSValue _socket_startTls(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_startTls(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
if (!socket->_tls) {
if (!socket->_tls)
{
tf_tls_context_t* context = 0;
if (argc > 0 && JS_IsObject(argv[0])) {
if (argc > 0 && JS_IsObject(argv[0]))
{
context = tf_tls_context_wrapper_get(argv[0]);
} else {
if (!_defaultTlsContext) {
}
else
{
if (!_defaultTlsContext)
{
_defaultTlsContext = tf_tls_context_create();
}
context = _defaultTlsContext;
}
if (context) {
if (context)
{
socket->_tls = tf_tls_context_create_session(context);
}
if (socket->_tls) {
if (socket->_tls)
{
tf_tls_session_set_hostname(socket->_tls, socket->_peerName);
if (socket->_direction == kAccept) {
if (socket->_direction == kAccept)
{
tf_tls_session_start_accept(socket->_tls);
} else if (socket->_direction == kConnect) {
}
else if (socket->_direction == kConnect)
{
tf_tls_session_start_connect(socket->_tls);
}
socket->_startTlsPromise = tf_task_allocate_promise(socket->_task);
JSValue result = tf_task_get_promise(socket->_task, socket->_startTlsPromise);
_socket_processOutgoingTls(socket);
return result;
} else {
}
else
{
return JS_ThrowInternalError(tf_task_get_context(socket->_task), "Failed to get TLS context");
}
} else {
}
else
{
return JS_ThrowInternalError(tf_task_get_context(socket->_task), "startTls with TLS already started");
}
}
JSValue _socket_stopTls(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_stopTls(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
if (socket->_tls) {
if (socket->_tls)
{
_socket_processOutgoingTls(socket);
tf_tls_session_destroy(socket->_tls);
socket->_tls = NULL;
} else {
}
else
{
JS_ThrowInternalError(tf_task_get_context(socket->_task), "stopTls with TLS already stopped");
}
return JS_NULL;
}
bool _socket_processSomeOutgoingTls(socket_t* socket, promiseid_t promise, uv_write_cb callback) {
bool _socket_processSomeOutgoingTls(socket_t* socket, promiseid_t promise, uv_write_cb callback)
{
char buffer[65536];
int result = tf_tls_session_read_encrypted(socket->_tls, buffer, sizeof(buffer));
if (result > 0) {
if (result > 0)
{
char* request_buffer = malloc(sizeof(uv_write_t) + result);
uv_write_t* request = (uv_write_t*)request_buffer;
memset(request, 0, sizeof(*request));
@ -279,23 +317,30 @@ bool _socket_processSomeOutgoingTls(socket_t* socket, promiseid_t promise, uv_wr
};
int writeResult = uv_write(request, (uv_stream_t*)&socket->_socket, &writeBuffer, 1, callback);
if (writeResult != 0) {
if (writeResult != 0)
{
free(request_buffer);
char error[256];
snprintf(error, sizeof(error), "uv_write: %s", uv_strerror(writeResult));
_socket_reportError(socket, error);
}
} else {
}
else
{
_socket_reportTlsErrors(socket);
}
return result > 0;
}
void _socket_processOutgoingTls(socket_t* socket) {
while (_socket_processSomeOutgoingTls(socket, -1, _socket_onWrite)) {}
void _socket_processOutgoingTls(socket_t* socket)
{
while (_socket_processSomeOutgoingTls(socket, -1, _socket_onWrite))
{
}
}
JSValue _socket_bind(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_bind(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
const char* node = JS_ToCString(tf_task_get_context(socket->_task), argv[0]);
const char* port = JS_ToCString(tf_task_get_context(socket->_task), argv[1]);
@ -313,7 +358,8 @@ JSValue _socket_bind(JSContext* context, JSValueConst this_val, int argc, JSValu
data->promise = tf_task_allocate_promise(socket->_task);
int result = uv_getaddrinfo(tf_task_get_loop(socket->_task), &data->resolver, _socket_onResolvedForBind, node, port, &hints);
if (result != 0) {
if (result != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_getaddrinfo: %s", uv_strerror(result));
tf_task_reject_promise(socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(socket->_task), error));
@ -322,26 +368,34 @@ JSValue _socket_bind(JSContext* context, JSValueConst this_val, int argc, JSValu
return tf_task_get_promise(socket->_task, data->promise);
}
void _socket_onResolvedForBind(uv_getaddrinfo_t* resolver, int status, struct addrinfo* result) {
void _socket_onResolvedForBind(uv_getaddrinfo_t* resolver, int status, struct addrinfo* result)
{
socket_resolve_data_t* data = (socket_resolve_data_t*)resolver->data;
if (status != 0) {
if (status != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_getaddrinfo: %s", uv_strerror(status));
tf_task_reject_promise(data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), error));
} else {
}
else
{
int bindResult = uv_tcp_bind(&data->socket->_socket, result->ai_addr, 0);
if (bindResult != 0) {
if (bindResult != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_tcp_bind: %s", uv_strerror(bindResult));
tf_task_reject_promise(data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), error));
} else {
}
else
{
tf_task_resolve_promise(data->socket->_task, data->promise, JS_UNDEFINED);
}
}
free(data);
}
JSValue _socket_connect(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_connect(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
socket->_direction = kConnect;
const char* node = JS_ToCString(context, argv[0]);
@ -363,7 +417,8 @@ JSValue _socket_connect(JSContext* context, JSValueConst this_val, int argc, JSV
data->promise = promise;
int result = uv_getaddrinfo(tf_task_get_loop(socket->_task), &data->resolver, _socket_onResolvedForConnect, node, port, &hints);
if (result != 0) {
if (result != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_getaddrinfo: %s", uv_strerror(result));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(context, "%s", error));
@ -375,18 +430,23 @@ JSValue _socket_connect(JSContext* context, JSValueConst this_val, int argc, JSV
return tf_task_get_promise(socket->_task, promise);
}
void _socket_onResolvedForConnect(uv_getaddrinfo_t* resolver, int status, struct addrinfo* result) {
void _socket_onResolvedForConnect(uv_getaddrinfo_t* resolver, int status, struct addrinfo* result)
{
socket_resolve_data_t* data = resolver->data;
if (status != 0) {
if (status != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_getaddrinfo: %s", uv_strerror(status));
tf_task_reject_promise(data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), "%s", error));
} else {
}
else
{
uv_connect_t* request = malloc(sizeof(uv_connect_t));
memset(request, 0, sizeof(*request));
request->data = (void*)(intptr_t)data->promise;
int connectResult = uv_tcp_connect(request, &data->socket->_socket, result->ai_addr, _socket_onConnect);
if (connectResult != 0) {
if (connectResult != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_tcp_connect: %s", uv_strerror(connectResult));
tf_task_reject_promise(data->socket->_task, data->promise, JS_ThrowInternalError(tf_task_get_context(data->socket->_task), "%s", error));
@ -396,14 +456,19 @@ void _socket_onResolvedForConnect(uv_getaddrinfo_t* resolver, int status, struct
free(data);
}
void _socket_onConnect(uv_connect_t* request, int status) {
void _socket_onConnect(uv_connect_t* request, int status)
{
promiseid_t promise = (intptr_t)request->data;
if (promise != -1) {
if (promise != -1)
{
socket_t* socket = request->handle->data;
if (status == 0) {
if (status == 0)
{
socket->_connected = true;
tf_task_resolve_promise(socket->_task, promise, JS_NewInt32(tf_task_get_context(socket->_task), status));
} else {
}
else
{
char error[256];
snprintf(error, sizeof(error), "uv_tcp_connect: %s", uv_strerror(status));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(tf_task_get_context(socket->_task), "%s", error));
@ -412,29 +477,37 @@ void _socket_onConnect(uv_connect_t* request, int status) {
free(request);
}
JSValue _socket_listen(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_listen(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
int backlog = 1;
JS_ToInt32(context, &backlog, argv[0]);
if (JS_IsUndefined(socket->_onConnect)) {
if (JS_IsUndefined(socket->_onConnect))
{
socket->_onConnect = JS_DupValue(context, argv[1]);
int result = uv_listen((uv_stream_t*)&socket->_socket, backlog, _socket_onNewConnection);
if (result != 0) {
if (result != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_listen: %s", uv_strerror(result));
return JS_ThrowInternalError(context, error);
}
return JS_NewInt32(context, result);
} else {
}
else
{
return JS_ThrowInternalError(context, "listen: Already listening.");
}
}
void _socket_onNewConnection(uv_stream_t* server, int status) {
void _socket_onNewConnection(uv_stream_t* server, int status)
{
socket_t* socket = server->data;
if (!JS_IsUndefined(socket->_onConnect)) {
if (!JS_IsUndefined(socket->_onConnect))
{
JSValue result = JS_Call(tf_task_get_context(socket->_task), socket->_onConnect, socket->_object, 0, NULL);
if (JS_IsException(result)) {
if (JS_IsException(result))
{
printf("Socket error on connection.\n");
js_std_dump_error(tf_task_get_context(socket->_task));
}
@ -442,7 +515,8 @@ void _socket_onNewConnection(uv_stream_t* server, int status) {
}
}
JSValue _socket_accept(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_accept(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
socket_t* client = _socket_create_internal(context);
@ -450,10 +524,13 @@ JSValue _socket_accept(JSContext* context, JSValueConst this_val, int argc, JSVa
promiseid_t promise = tf_task_allocate_promise(socket->_task);
JSValue result = tf_task_get_promise(socket->_task, promise);
int status = uv_accept((uv_stream_t*)&socket->_socket, (uv_stream_t*)&client->_socket);
if (status == 0) {
if (status == 0)
{
client->_connected = true;
tf_task_resolve_promise(socket->_task, promise, client->_object);
} else {
}
else
{
char error[256];
snprintf(error, sizeof(error), "uv_accept: %s", uv_strerror(status));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(context, error));
@ -461,9 +538,11 @@ JSValue _socket_accept(JSContext* context, JSValueConst this_val, int argc, JSVa
return result;
}
JSValue _socket_close(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_close(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
if (socket->_closePromise == -1) {
if (socket->_closePromise == -1)
{
socket->_closePromise = tf_task_allocate_promise(socket->_task);
JSValue result = tf_task_get_promise(socket->_task, socket->_closePromise);
_socket_close_internal(socket);
@ -472,24 +551,30 @@ JSValue _socket_close(JSContext* context, JSValueConst this_val, int argc, JSVal
return JS_UNDEFINED;
}
JSValue _socket_shutdown(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_shutdown(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
promiseid_t promise = tf_task_allocate_promise(socket->_task);
JSValue result = tf_task_get_promise(socket->_task, promise);
if (socket->_tls) {
if (socket->_tls)
{
_socket_processTlsShutdown(socket, promise);
} else {
}
else
{
_socket_shutdownInternal(socket, promise);
}
return result;
}
void _socket_shutdownInternal(socket_t* socket, promiseid_t promise) {
void _socket_shutdownInternal(socket_t* socket, promiseid_t promise)
{
uv_shutdown_t* request = malloc(sizeof(uv_shutdown_t));
memset(request, 0, sizeof(*request));
request->data = (void*)(intptr_t)promise;
int result = uv_shutdown(request, (uv_stream_t*)&socket->_socket, _socket_onShutdown);
if (result != 0) {
if (result != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_shutdown: %s", uv_strerror(result));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(tf_task_get_context(socket->_task), "%s", error));
@ -497,23 +582,28 @@ void _socket_shutdownInternal(socket_t* socket, promiseid_t promise) {
}
}
void _socket_processTlsShutdown(socket_t* socket, promiseid_t promise) {
void _socket_processTlsShutdown(socket_t* socket, promiseid_t promise)
{
tf_tls_session_shutdown(socket->_tls);
if (!_socket_processSomeOutgoingTls(socket, promise, _socket_onTlsShutdown)) {
if (!_socket_processSomeOutgoingTls(socket, promise, _socket_onTlsShutdown))
{
_socket_shutdownInternal(socket, promise);
}
}
void _socket_onTlsShutdown(uv_write_t* request, int status) {
void _socket_onTlsShutdown(uv_write_t* request, int status)
{
socket_t* socket = request->handle->data;
promiseid_t promise = (intptr_t)request->data;
_socket_processTlsShutdown(socket, promise);
free(request);
}
JSValue _socket_onError(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_onError(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
if (!JS_IsUndefined(socket->_onError)) {
if (!JS_IsUndefined(socket->_onError))
{
JS_FreeValue(context, socket->_onError);
socket->_onError = JS_UNDEFINED;
}
@ -521,34 +611,43 @@ JSValue _socket_onError(JSContext* context, JSValueConst this_val, int argc, JSV
return JS_NULL;
}
JSValue _socket_read(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_read(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
socket->_onRead = JS_DupValue(context, argv[0]);
int result = uv_read_start((uv_stream_t*)&socket->_socket, _socket_allocateBuffer, _socket_onRead);
promiseid_t promise = tf_task_allocate_promise(socket->_task);
JSValue read_result = tf_task_get_promise(socket->_task, promise);
if (result != 0) {
if (result != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_read_start: %s", uv_strerror(result));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(context, error));
} else {
}
else
{
tf_task_resolve_promise(socket->_task, promise, JS_UNDEFINED);
}
return read_result;
}
void _socket_allocateBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf) {
void _socket_allocateBuffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf)
{
*buf = uv_buf_init(malloc(suggestedSize), suggestedSize);
}
void _socket_onRead(uv_stream_t* stream, ssize_t readSize, const uv_buf_t* buffer) {
void _socket_onRead(uv_stream_t* stream, ssize_t readSize, const uv_buf_t* buffer)
{
socket_t* socket = stream->data;
if (readSize <= 0) {
if (readSize <= 0)
{
socket->_connected = false;
if (!JS_IsUndefined(socket->_onRead)) {
if (!JS_IsUndefined(socket->_onRead))
{
JSValue args[] = { JS_UNDEFINED };
JSValue result = JS_Call(tf_task_get_context(socket->_task), socket->_onRead, socket->_object, 1, args);
if (JS_IsException(result)) {
if (JS_IsException(result))
{
printf("Socket error on read.\n");
js_std_dump_error(tf_task_get_context(socket->_task));
}
@ -556,42 +655,60 @@ void _socket_onRead(uv_stream_t* stream, ssize_t readSize, const uv_buf_t* buffe
tf_task_run_jobs(socket->_task);
}
_socket_close_internal(socket);
} else {
if (socket->_tls) {
}
else
{
if (socket->_tls)
{
_socket_reportTlsErrors(socket);
tf_tls_session_write_encrypted(socket->_tls, buffer->base, readSize);
if (socket->_startTlsPromise != -1) {
if (socket->_startTlsPromise != -1)
{
tf_tls_handshake_t result = tf_tls_session_handshake(socket->_tls);
if (result == k_tls_handshake_done) {
if (result == k_tls_handshake_done)
{
promiseid_t promise = socket->_startTlsPromise;
socket->_startTlsPromise = -1;
tf_task_resolve_promise(socket->_task, promise, JS_UNDEFINED);
} else if (result == k_tls_handshake_failed) {
}
else if (result == k_tls_handshake_failed)
{
promiseid_t promise = socket->_startTlsPromise;
socket->_startTlsPromise = -1;
char buffer[8192];
if (tf_tls_session_get_error(socket->_tls, buffer, sizeof(buffer))) {
if (tf_tls_session_get_error(socket->_tls, buffer, sizeof(buffer)))
{
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(tf_task_get_context(socket->_task), buffer));
} else {
}
else
{
tf_task_reject_promise(socket->_task, promise, JS_UNDEFINED);
}
}
}
while (true) {
while (true)
{
char plain[8192];
int result = tf_tls_session_read_plain(socket->_tls, plain, sizeof(plain));
if (result > 0) {
if (result > 0)
{
_socket_notifyDataRead(socket, plain, result);
} else if (result == k_tls_read_failed) {
}
else if (result == k_tls_read_failed)
{
_socket_reportTlsErrors(socket);
_socket_close_internal(socket);
break;
} else if (result == k_tls_read_zero) {
if (!JS_IsUndefined(socket->_onRead)) {
}
else if (result == k_tls_read_zero)
{
if (!JS_IsUndefined(socket->_onRead))
{
JSValue args[] = { JS_UNDEFINED };
JSValue result = JS_Call(tf_task_get_context(socket->_task), socket->_onRead, socket->_object, 1, args);
if (JS_IsException(result)) {
if (JS_IsException(result))
{
printf("Socket error on read plain.\n");
js_std_dump_error(tf_task_get_context(socket->_task));
}
@ -599,21 +716,27 @@ void _socket_onRead(uv_stream_t* stream, ssize_t readSize, const uv_buf_t* buffe
tf_task_run_jobs(socket->_task);
}
break;
} else {
}
else
{
break;
}
}
if (socket->_tls) {
if (socket->_tls)
{
_socket_processOutgoingTls(socket);
}
} else {
}
else
{
_socket_notifyDataRead(socket, buffer->base, readSize);
}
}
free(buffer->base);
}
static JSValue _newUint8Array(JSContext* context, const void* data, size_t length) {
static JSValue _newUint8Array(JSContext* context, const void* data, size_t length)
{
JSValue arrayBuffer = JS_NewArrayBufferCopy(context, (const uint8_t*)data, length);
JSValue global = JS_GetGlobalObject(context);
JSValue constructor = JS_GetPropertyStr(context, global, "Uint8Array");
@ -624,13 +747,17 @@ static JSValue _newUint8Array(JSContext* context, const void* data, size_t lengt
return typedArray;
}
void _socket_notifyDataRead(socket_t* socket, const char* data, size_t length) {
if (!JS_IsUndefined(socket->_onRead)) {
if (data && length > 0) {
void _socket_notifyDataRead(socket_t* socket, const char* data, size_t length)
{
if (!JS_IsUndefined(socket->_onRead))
{
if (data && length > 0)
{
JSValue typedArray = _newUint8Array(tf_task_get_context(socket->_task), data, length);
JSValue args[] = { typedArray };
JSValue result = JS_Call(tf_task_get_context(socket->_task), socket->_onRead, socket->_object, 1, args);
if (JS_IsException(result)) {
if (JS_IsException(result))
{
printf("Socket error on data read.\n");
js_std_dump_error(tf_task_get_context(socket->_task));
}
@ -641,36 +768,45 @@ void _socket_notifyDataRead(socket_t* socket, const char* data, size_t length) {
}
}
int _socket_writeBytes(socket_t* socket, promiseid_t promise, int (*callback)(socket_t* socket, promiseid_t promise, const char*, size_t), JSValue value, int* outLength) {
int _socket_writeBytes(socket_t* socket, promiseid_t promise, int (*callback)(socket_t* socket, promiseid_t promise, const char*, size_t), JSValue value, int* outLength)
{
int result = -1;
size_t length;
uint8_t* array = NULL;
JSContext* context = tf_task_get_context(socket->_task);
if (JS_IsString(value)) {
if (JS_IsString(value))
{
const char* stringValue = JS_ToCStringLen(context, &length, value);
result = callback(socket, promise, stringValue, length);
JS_FreeCString(context, stringValue);
} else if ((array = tf_try_get_array_buffer(context, &length, value)) != 0) {
}
else if ((array = tf_try_get_array_buffer(context, &length, value)) != 0)
{
result = callback(socket, promise, (const char*)array, length);
} else {
}
else
{
size_t offset;
size_t element_size;
JSValue buffer = tf_try_get_typed_array_buffer(context, value, &offset, &length, &element_size);
size_t size;
if ((array = tf_try_get_array_buffer(context, &size, buffer)) != 0) {
if ((array = tf_try_get_array_buffer(context, &size, buffer)) != 0)
{
result = callback(socket, promise, (const char*)array, length);
}
JS_FreeValue(context, buffer);
}
if (outLength) {
if (outLength)
{
*outLength = (int)length;
}
return result;
}
int _socket_writeInternal(socket_t* socket, promiseid_t promise, const char* data, size_t length) {
int _socket_writeInternal(socket_t* socket, promiseid_t promise, const char* data, size_t length)
{
char* rawBuffer = malloc(sizeof(uv_write_t) + length);
uv_write_t* request = (uv_write_t*)rawBuffer;
memcpy(rawBuffer + sizeof(uv_write_t), data, length);
@ -684,51 +820,70 @@ int _socket_writeInternal(socket_t* socket, promiseid_t promise, const char* dat
return uv_write(request, (uv_stream_t*)&socket->_socket, &buffer, 1, _socket_onWrite);
}
static int _socket_write_tls(socket_t* socket, promiseid_t promise, const char* data, size_t size) {
static int _socket_write_tls(socket_t* socket, promiseid_t promise, const char* data, size_t size)
{
return tf_tls_session_write_plain(socket->_tls, data, size);
}
JSValue _socket_write(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_write(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
promiseid_t promise = tf_task_allocate_promise(socket->_task);
JSValue write_result = tf_task_get_promise(socket->_task, promise);
if (!JS_IsUndefined(argv[0])) {
if (socket->_tls) {
if (!JS_IsUndefined(argv[0]))
{
if (socket->_tls)
{
_socket_reportTlsErrors(socket);
int length = 0;
int result = _socket_writeBytes(socket, -1, _socket_write_tls, argv[0], &length);
char buffer[8192];
if (result <= 0 && tf_tls_session_get_error(socket->_tls, buffer, sizeof(buffer))) {
if (result <= 0 && tf_tls_session_get_error(socket->_tls, buffer, sizeof(buffer)))
{
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(context, buffer));
} else if (result < length) {
}
else if (result < length)
{
tf_task_reject_promise(socket->_task, promise, JS_NewInt32(context, result));
} else {
}
else
{
tf_task_resolve_promise(socket->_task, promise, JS_NewInt32(context, result));
}
_socket_processOutgoingTls(socket);
} else {
}
else
{
int length;
int result = _socket_writeBytes(socket, promise, _socket_writeInternal, argv[0], &length);
if (result != 0) {
if (result != 0)
{
char error[256];
snprintf(error, sizeof(error), "uv_write: %s", uv_strerror(result));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(context, error));
}
}
} else {
}
else
{
tf_task_reject_promise(socket->_task, promise, JS_NewInt32(context, -2));
}
return write_result;
}
void _socket_onWrite(uv_write_t* request, int status) {
void _socket_onWrite(uv_write_t* request, int status)
{
socket_t* socket = request->handle->data;
promiseid_t promise = (intptr_t)request->data;
if (promise != -1) {
if (status == 0) {
if (promise != -1)
{
if (status == 0)
{
tf_task_resolve_promise(socket->_task, promise, JS_NewInt32(tf_task_get_context(socket->_task), status));
} else {
}
else
{
char error[256];
snprintf(error, sizeof(error), "uv_write: %s", uv_strerror(status));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(tf_task_get_context(socket->_task), error));
@ -737,15 +892,18 @@ void _socket_onWrite(uv_write_t* request, int status) {
free(request);
}
JSValue _socket_isConnected(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_isConnected(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
return socket->_connected ? JS_TRUE : JS_FALSE;
}
void _socket_onClose(uv_handle_t* handle) {
void _socket_onClose(uv_handle_t* handle)
{
--_open_count;
socket_t* socket = handle->data;
if (socket->_closePromise != -1) {
if (socket->_closePromise != -1)
{
promiseid_t promise = socket->_closePromise;
socket->_closePromise = -1;
socket->_connected = false;
@ -753,12 +911,16 @@ void _socket_onClose(uv_handle_t* handle) {
}
}
void _socket_onShutdown(uv_shutdown_t* request, int status) {
void _socket_onShutdown(uv_shutdown_t* request, int status)
{
socket_t* socket = request->handle->data;
promiseid_t promise = (intptr_t)request->data;
if (status == 0) {
if (status == 0)
{
tf_task_resolve_promise(socket->_task, promise, JS_UNDEFINED);
} else {
}
else
{
char error[256];
snprintf(error, sizeof(error), "uv_shutdown: %s", uv_strerror(status));
tf_task_reject_promise(socket->_task, promise, JS_ThrowInternalError(tf_task_get_context(socket->_task), "%s", error));
@ -766,18 +928,25 @@ void _socket_onShutdown(uv_shutdown_t* request, int status) {
free(request);
}
JSValue _socket_getPeerName(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_getPeerName(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
struct sockaddr_in6 addr;
int nameLength = sizeof(addr);
if (uv_tcp_getpeername(&socket->_socket, (struct sockaddr*)&addr, &nameLength) == 0) {
if (uv_tcp_getpeername(&socket->_socket, (struct sockaddr*)&addr, &nameLength) == 0)
{
char name[1024];
if ((size_t)nameLength > sizeof(struct sockaddr_in)) {
if (uv_ip6_name(&addr, name, sizeof(name)) == 0) {
if ((size_t)nameLength > sizeof(struct sockaddr_in))
{
if (uv_ip6_name(&addr, name, sizeof(name)) == 0)
{
return JS_NewString(context, name);
}
} else {
if (uv_ip4_name((struct sockaddr_in*)&addr, name, sizeof(name)) == 0) {
}
else
{
if (uv_ip4_name((struct sockaddr_in*)&addr, name, sizeof(name)) == 0)
{
return JS_NewString(context, name);
}
}
@ -785,24 +954,29 @@ JSValue _socket_getPeerName(JSContext* context, JSValueConst this_val, int argc,
return JS_UNDEFINED;
}
JSValue _socket_getPeerCertificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_getPeerCertificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
if (socket->_tls) {
if (socket->_tls)
{
char buffer[128 * 1024];
int result = tf_tls_session_get_peer_certificate(socket->_tls, buffer, sizeof(buffer));
if (result > 0) {
if (result > 0)
{
return _newUint8Array(tf_task_get_context(socket->_task), buffer, sizeof(buffer));
}
}
return JS_UNDEFINED;
}
JSValue _socket_getNoDelay(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_getNoDelay(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
return JS_NewBool(context, socket->_noDelay);
}
JSValue _socket_setNoDelay(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _socket_setNoDelay(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
socket_t* socket = JS_GetOpaque(this_val, _classId);
int result = JS_ToBool(context, argv[0]);
socket->_noDelay = result > 0;

638
src/ssb.c

File diff suppressed because it is too large Load Diff

View File

@ -22,14 +22,16 @@ typedef struct _tf_ssb_connections_t
static void _tf_ssb_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_change_t change, tf_ssb_connection_t* connection, void* user_data)
{
tf_ssb_connections_t* connections = user_data;
switch (change) {
switch (change)
{
case k_tf_ssb_change_create:
{
char key[ID_BASE64_LEN];
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_store(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);
}
@ -38,7 +40,8 @@ static void _tf_ssb_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_change_t
case k_tf_ssb_change_connect:
{
char key[ID_BASE64_LEN];
if (tf_ssb_connection_get_id(connection, key, sizeof(key))) {
if (tf_ssb_connection_get_id(connection, key, sizeof(key)))
{
tf_ssb_connections_set_succeeded(connections, tf_ssb_connection_get_host(connection), tf_ssb_connection_get_port(connection), key);
}
}
@ -52,16 +55,20 @@ static bool _tf_ssb_connections_get_next_connection(tf_ssb_connections_t* connec
{
bool result = false;
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->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, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(connections->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, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_int(statement, 1, 60000) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW) {
sqlite3_step(statement) == SQLITE_ROW)
{
snprintf(host, host_size, "%s", sqlite3_column_text(statement, 0));
*port = sqlite3_column_int(statement, 1);
snprintf(key, key_size, "%s", sqlite3_column_text(statement, 2));
result = true;
}
sqlite3_finalize(statement);
} else {
}
else
{
printf("prepare: %s\n", sqlite3_errmsg(connections->db));
}
return result;
@ -72,13 +79,16 @@ static void _tf_ssb_connections_timer(uv_timer_t* timer)
tf_ssb_connections_t* connections = timer->data;
tf_ssb_connection_t* active[4];
int count = tf_ssb_get_connections(connections->ssb, active, _countof(active));
if (count < _countof(active)) {
if (count < _countof(active))
{
char host[256];
int port;
char key[ID_BASE64_LEN];
if (_tf_ssb_connections_get_next_connection(connections, host, sizeof(host), &port, key, sizeof(key))) {
if (_tf_ssb_connections_get_next_connection(connections, host, sizeof(host), &port, key, sizeof(key)))
{
uint8_t key_bin[ID_BIN_LEN];
if (tf_ssb_id_str_to_bin(key_bin, key)) {
if (tf_ssb_id_str_to_bin(key_bin, key))
{
tf_ssb_connect(connections->ssb, host, port, key_bin);
}
}
@ -118,12 +128,15 @@ void tf_ssb_connections_destroy(tf_ssb_connections_t* connections)
void tf_ssb_connections_store(tf_ssb_connections_t* connections, const char* host, int port, const char* key)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->db, "INSERT INTO connections (host, port, key) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(connections->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, host, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 2, port) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, key, -1, NULL) == SQLITE_OK) {
sqlite3_bind_text(statement, 3, key, -1, NULL) == SQLITE_OK)
{
int r = sqlite3_step(statement);
if (r != SQLITE_DONE) {
if (r != SQLITE_DONE)
{
printf("tf_ssb_connections_store: %d, %s.\n", r, sqlite3_errmsg(connections->db));
}
}
@ -134,11 +147,14 @@ void tf_ssb_connections_store(tf_ssb_connections_t* connections, const char* hos
void tf_ssb_connections_set_attempted(tf_ssb_connections_t* connections, const char* host, int port, const char* key)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->db, "UPDATE connections SET last_attempt = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(connections->db, "UPDATE connections SET last_attempt = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, host, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 2, port) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, key, -1, NULL) == SQLITE_OK) {
if (sqlite3_step(statement) != SQLITE_DONE) {
sqlite3_bind_text(statement, 3, key, -1, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) != SQLITE_DONE)
{
printf("tf_ssb_connections_set_attempted: %s.\n", sqlite3_errmsg(connections->db));
}
}
@ -149,11 +165,14 @@ void tf_ssb_connections_set_attempted(tf_ssb_connections_t* connections, const c
void tf_ssb_connections_set_succeeded(tf_ssb_connections_t* connections, const char* host, int port, const char* key)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(connections->db, "UPDATE connections SET last_success = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(connections->db, "UPDATE connections SET last_success = strftime('%s', 'now') WHERE host = $1 AND port = $2 AND key = $3", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, host, -1, NULL) == SQLITE_OK &&
sqlite3_bind_int(statement, 2, port) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, key, -1, NULL) == SQLITE_OK) {
if (sqlite3_step(statement) != SQLITE_DONE) {
sqlite3_bind_text(statement, 3, key, -1, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) != SQLITE_DONE)
{
printf("tf_ssb_connections_set_succeeded: %s.\n", sqlite3_errmsg(connections->db));
}
}

View File

@ -82,7 +82,8 @@ bool tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id,
sqlite3_stmt* statement;
int64_t last_row_id = -1;
const char* query = "INSERT INTO messages (id, previous, author, sequence, timestamp, content, hash, signature) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT DO NOTHING";
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 &&
(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 &&
@ -90,9 +91,11 @@ bool tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id,
sqlite3_bind_int64(statement, 5, timestamp) == SQLITE_OK &&
sqlite3_bind_text(statement, 6, contentstr, 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, 8, signature, -1, NULL) == SQLITE_OK)
{
int r = sqlite3_step(statement);
if (r != SQLITE_DONE) {
if (r != SQLITE_DONE)
{
printf("%s\n", sqlite3_errmsg(db));
}
stored = r == SQLITE_DONE && sqlite3_changes(db) != 0;
@ -102,27 +105,34 @@ bool tf_ssb_db_store_message(tf_ssb_t* ssb, JSContext* context, const char* id,
}
}
sqlite3_finalize(statement);
} else {
}
else
{
printf("prepare failed: %s\n", sqlite3_errmsg(db));
}
if (last_row_id != -1)
{
query = "INSERT INTO blob_wants (id) 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 ON CONFLICT DO NOTHING RETURNING id";
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_int64(statement, 1, last_row_id) == SQLITE_OK &&
sqlite3_bind_int(statement, 2, BLOB_ID_LEN - 1) == SQLITE_OK) {
sqlite3_bind_int(statement, 2, BLOB_ID_LEN - 1) == SQLITE_OK)
{
int r = SQLITE_OK;
while ((r = sqlite3_step(statement)) == SQLITE_ROW)
{
tf_ssb_notify_blob_want_added(ssb, (const char*)sqlite3_column_text(statement, 0));
}
if (r != SQLITE_DONE) {
if (r != SQLITE_DONE)
{
printf("%s\n", sqlite3_errmsg(db));
}
}
sqlite3_finalize(statement);
} else {
}
else
{
printf("prepare failed: %s\n", sqlite3_errmsg(db));
}
}
@ -141,17 +151,21 @@ bool tf_ssb_db_message_content_get(tf_ssb_t* ssb, const char* id, uint8_t** out_
bool result = false;
sqlite3_stmt* statement;
const char* query = "SELECT content FROM messages WHERE id = ?";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW) {
sqlite3_step(statement) == SQLITE_ROW)
{
const uint8_t* blob = sqlite3_column_blob(statement, 0);
int size = sqlite3_column_bytes(statement, 0);
if (out_blob) {
if (out_blob)
{
*out_blob = malloc(size + 1);
memcpy(*out_blob, blob, size);
(*out_blob)[size] = '\0';
}
if (out_size) {
if (out_size)
{
*out_size = size;
}
result = true;
@ -166,17 +180,21 @@ bool tf_ssb_db_blob_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_
bool result = false;
sqlite3_stmt* statement;
const char* query = "SELECT content FROM blobs WHERE id = $1";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW) {
sqlite3_step(statement) == SQLITE_ROW)
{
const uint8_t* blob = sqlite3_column_blob(statement, 0);
int size = sqlite3_column_bytes(statement, 0);
if (out_blob) {
if (out_blob)
{
*out_blob = malloc(size + 1);
memcpy(*out_blob, blob, size);
(*out_blob)[size] = '\0';
}
if (out_size) {
if (out_size)
{
*out_size = size;
}
result = true;
@ -203,19 +221,26 @@ bool tf_ssb_db_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char*
printf("blob store %s\n", id);
const char* query = "INSERT INTO blobs (id, content, created) VALUES ($1, $2, CAST(strftime('%s') AS INTEGER)) ON CONFLICT DO NOTHING";
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 &&
sqlite3_bind_blob(statement, 2, blob, size, NULL) == SQLITE_OK) {
sqlite3_bind_blob(statement, 2, blob, size, NULL) == SQLITE_OK)
{
result = sqlite3_step(statement) == SQLITE_DONE;
} else {
}
else
{
printf("bind failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
} else {
}
else
{
printf("prepare failed: %s\n", sqlite3_errmsg(db));
}
if (result && out_id) {
if (result && out_id)
{
snprintf(out_id, out_id_size, "%s", id);
}
return result;
@ -226,23 +251,30 @@ bool tf_ssb_db_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* aut
bool found = false;
sqlite3_stmt* statement;
const char* query = "SELECT id, timestamp, content FROM messages WHERE author = $1 AND sequence = $2";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(tf_ssb_get_db(ssb), 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 &&
sqlite3_step(statement) == SQLITE_ROW) {
if (out_message_id) {
sqlite3_step(statement) == SQLITE_ROW)
{
if (out_message_id)
{
strncpy(out_message_id, (const char*)sqlite3_column_text(statement, 0), out_message_id_size - 1);
}
if (out_timestamp) {
if (out_timestamp)
{
*out_timestamp = sqlite3_column_int64(statement, 1);
}
if (out_content) {
if (out_content)
{
*out_content = strdup((const char*)sqlite3_column_text(statement, 2));
}
found = true;
}
sqlite3_finalize(statement);
} else {
}
else
{
printf("prepare failed: %s\n", sqlite3_errmsg(tf_ssb_get_db(ssb)));
}
return found;
@ -253,77 +285,105 @@ bool tf_ssb_db_get_latest_message_by_author(tf_ssb_t* ssb, const char* author, i
bool found = false;
sqlite3_stmt* statement;
const char* query = "SELECT id, sequence FROM messages WHERE author = $1 AND sequence = (SELECT MAX(sequence) FROM messages WHERE author = $1)";
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(tf_ssb_get_db(ssb), query, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, author, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW) {
if (out_sequence) {
sqlite3_step(statement) == SQLITE_ROW)
{
if (out_sequence)
{
*out_sequence = sqlite3_column_int64(statement, 1);
}
if (out_message_id) {
if (out_message_id)
{
strncpy(out_message_id, (const char*)sqlite3_column_text(statement, 0), out_message_id_size - 1);
}
found = true;
}
sqlite3_finalize(statement);
} else {
}
else
{
printf("prepare failed: %s\n", sqlite3_errmsg(tf_ssb_get_db(ssb)));
}
return found;
}
static bool _tf_ssb_sqlite_bind_json(JSContext* context, sqlite3* db, sqlite3_stmt* statement, JSValue binds) {
static bool _tf_ssb_sqlite_bind_json(JSContext* context, sqlite3* db, sqlite3_stmt* statement, JSValue binds)
{
bool all_bound = true;
int32_t length = 0;
if (JS_IsUndefined(binds)) {
if (JS_IsUndefined(binds))
{
return true;
}
JSValue lengthval = JS_GetPropertyStr(context, binds, "length");
if (JS_ToInt32(context, &length, lengthval) == 0) {
for (int i = 0; i < length; i++) {
if (JS_ToInt32(context, &length, lengthval) == 0)
{
for (int i = 0; i < length; i++)
{
JSValue value = JS_GetPropertyUint32(context, binds, i);
if (JS_IsString(value)) {
if (JS_IsString(value))
{
size_t str_len = 0;
const char* str = JS_ToCStringLen(context, &str_len, value);
if (str) {
if (sqlite3_bind_text(statement, i + 1, str, str_len, SQLITE_TRANSIENT) != SQLITE_OK) {
if (str)
{
if (sqlite3_bind_text(statement, i + 1, str, str_len, SQLITE_TRANSIENT) != SQLITE_OK)
{
printf("failed to bind: %s\n", sqlite3_errmsg(db));
all_bound = false;
}
JS_FreeCString(context, str);
} else {
}
else
{
printf("expected cstring\n");
}
} else if (JS_IsNumber(value)) {
}
else if (JS_IsNumber(value))
{
int64_t number = 0;
JS_ToInt64(context, &number, value);
if (sqlite3_bind_int64(statement, i + 1, number) != SQLITE_OK) {
if (sqlite3_bind_int64(statement, i + 1, number) != SQLITE_OK)
{
printf("failed to bind: %s\n", sqlite3_errmsg(db));
all_bound = false;
}
} else if (JS_IsNull(value)) {
if (sqlite3_bind_null(statement, i + 1) != SQLITE_OK) {
}
else if (JS_IsNull(value))
{
if (sqlite3_bind_null(statement, i + 1) != SQLITE_OK)
{
printf("failed to bind: %s\n", sqlite3_errmsg(db));
all_bound = false;
}
} else {
}
else
{
const char* str = JS_ToCString(context, value);
printf("expected string: %s\n", str);
JS_FreeCString(context, str);
}
JS_FreeValue(context, value);
}
} else {
}
else
{
printf("expected array\n");
}
JS_FreeValue(context, lengthval);
return all_bound;
}
static JSValue _tf_ssb_sqlite_row_to_json(JSContext* context, sqlite3_stmt* row) {
static JSValue _tf_ssb_sqlite_row_to_json(JSContext* context, sqlite3_stmt* row)
{
JSValue result = JS_NewObject(context);
for (int i = 0; i < sqlite3_column_count(row); i++) {
for (int i = 0; i < sqlite3_column_count(row); i++)
{
const char* name = sqlite3_column_name(row, i);
switch (sqlite3_column_type(row, i)) {
switch (sqlite3_column_type(row, i))
{
case SQLITE_INTEGER:
JS_SetPropertyStr(context, result, name, JS_NewInt64(context, sqlite3_column_int64(row, i)));
break;
@ -346,7 +406,8 @@ static JSValue _tf_ssb_sqlite_row_to_json(JSContext* context, sqlite3_stmt* row)
static int _tf_ssb_sqlite_authorizer(void* user_data, int action_code, const char* arg0, const char* arg1, const char* arg2, const char* arg3)
{
switch (action_code) {
switch (action_code)
{
case SQLITE_SELECT:
case SQLITE_FUNCTION:
return SQLITE_OK;
@ -365,10 +426,13 @@ void tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3_stmt* statement;
sqlite3_set_authorizer(db, _tf_ssb_sqlite_authorizer, ssb);
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{
JSContext* context = tf_ssb_get_context(ssb);
if (_tf_ssb_sqlite_bind_json(context, db, statement, binds)) {
while (sqlite3_step(statement) == SQLITE_ROW) {
if (_tf_ssb_sqlite_bind_json(context, db, statement, binds))
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
JSValue row = _tf_ssb_sqlite_row_to_json(context, statement);
tf_trace_t* trace = tf_ssb_get_trace(ssb);
tf_trace_begin(trace, "callback");
@ -378,7 +442,9 @@ void tf_ssb_db_visit_query(tf_ssb_t* ssb, const char* query, const JSValue binds
}
}
sqlite3_finalize(statement);
} else {
}
else
{
printf("prepare failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_set_authorizer(db, NULL, NULL);

View File

@ -11,10 +11,13 @@
static void _write_file(const char* path, void* blob, size_t size)
{
FILE* file = fopen(path, "wb");
if (file) {
if (file)
{
fwrite(blob, 1, size, file);
fclose(file);
} else {
}
else
{
printf("Failed to open %s for write: %s.\n", path, strerror(errno));
}
}
@ -23,7 +26,8 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
{
char user[256] = { 0 };
char path[256] = { 0 };
if (sscanf(key, "/~%255[^/]/%255s", user, path) != 2) {
if (sscanf(key, "/~%255[^/]/%255s", user, path) != 2)
{
printf("Unable to export %s.\n", key);
return;
}
@ -31,12 +35,15 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
char app_blob_id[64] = { 0 };
sqlite3_stmt* statement;
if (sqlite3_prepare(tf_ssb_get_db(ssb), "SELECT value FROM properties WHERE id = $1 AND key = 'path:' || $2", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(tf_ssb_get_db(ssb), "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 &&
sqlite3_step(statement) == SQLITE_ROW) {
sqlite3_step(statement) == SQLITE_ROW)
{
int len = sqlite3_column_bytes(statement, 0);
if (len >= (int)sizeof(app_blob_id)) {
if (len >= (int)sizeof(app_blob_id))
{
len = sizeof(app_blob_id) - 1;
}
memcpy(app_blob_id, sqlite3_column_text(statement, 0), len);
@ -45,14 +52,16 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
sqlite3_finalize(statement);
}
if (!*app_blob_id) {
if (!*app_blob_id)
{
printf("Did not find app blob ID for %s.\n", key);
return;
}
uint8_t* blob = NULL;
size_t size = 0;
if (!tf_ssb_db_blob_get(ssb, app_blob_id, &blob, &size)) {
if (!tf_ssb_db_blob_get(ssb, app_blob_id, &blob, &size))
{
printf("Did not find blob for %s: %s.\n", key, app_blob_id);
return;
}
@ -66,17 +75,21 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
JSValue files = JS_GetPropertyStr(context, app, "files");
JSPropertyEnum* ptab = NULL;
uint32_t plen = 0;
if (JS_GetOwnPropertyNames(context, &ptab, &plen, files, JS_GPN_STRING_MASK) == 0) {
for (uint32_t i = 0; i < plen; ++i) {
if (JS_GetOwnPropertyNames(context, &ptab, &plen, files, JS_GPN_STRING_MASK) == 0)
{
for (uint32_t i = 0; i < plen; ++i)
{
JSPropertyDescriptor desc;
if (JS_GetOwnProperty(context, &desc, files, ptab[i].atom) == 1) {
if (JS_GetOwnProperty(context, &desc, files, ptab[i].atom) == 1)
{
JSValue key = JS_AtomToString(context, ptab[i].atom);
const char* file_name = JS_ToCString(context, key);
const char* blob_id = JS_ToCString(context, desc.value);
uint8_t* file_blob = NULL;
size_t file_size = 0;
if (tf_ssb_db_blob_get(ssb, blob_id, &file_blob, &file_size)) {
if (tf_ssb_db_blob_get(ssb, blob_id, &file_blob, &file_size))
{
snprintf(file_path, sizeof(file_path), "apps/%s/%s/%s", user, path, file_name);
_write_file(file_path, file_blob, file_size);
free(file_blob);
@ -90,7 +103,8 @@ void tf_ssb_export(tf_ssb_t* ssb, const char* key)
}
}
for (uint32_t i = 0; i < plen; ++i) {
for (uint32_t i = 0; i < plen; ++i)
{
JS_FreeAtom(context, ptab[i].atom);
}
js_free(context, ptab);

View File

@ -33,17 +33,22 @@ static void _tf_ssb_import_file_read(uv_fs_t* req)
{
tf_import_file_t* file = req->data;
char id[k_id_base64_len];
if (req->result >= 0) {
if (tf_ssb_db_blob_store(file->ssb, (const uint8_t*)file->data, req->result, id, sizeof(id))) {
if (req->result >= 0)
{
if (tf_ssb_db_blob_store(file->ssb, (const uint8_t*)file->data, req->result, id, sizeof(id)))
{
printf("Stored %s/%s as %s.\n", file->parent, file->name, id);
if (strcasecmp(file->name + strlen(file->name) - strlen(".json"), ".json") == 0) {
if (strcasecmp(file->name + strlen(file->name) - strlen(".json"), ".json") == 0)
{
sqlite3_stmt* statement;
if (sqlite3_prepare(tf_ssb_get_db(file->ssb), "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, 'path:' || $2, $3)", -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_prepare(tf_ssb_get_db(file->ssb), "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, 'path:' || $2, $3)", -1, &statement, NULL) == SQLITE_OK)
{
((char*)file->name)[strlen(file->name) - strlen(".json")] = '\0';
if (sqlite3_bind_text(statement, 1, file->user, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 2, file->name, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_DONE) {
sqlite3_step(statement) == SQLITE_DONE)
{
printf("Registered %s path:%s as %s.\n", file->user, file->name, id);
}
sqlite3_finalize(statement);
@ -75,13 +80,17 @@ static void _tf_ssb_import_scandir(uv_fs_t* req)
{
tf_import_t* import = req->data;
uv_dirent_t ent;
while (uv_fs_scandir_next(req, &ent) == 0) {
while (uv_fs_scandir_next(req, &ent) == 0)
{
size_t len = strlen(import->parent) + strlen(ent.name) + 2;
char* path = malloc(len);
snprintf(path, len, "%s/%s", import->parent, ent.name);
if (ent.type == UV_DIRENT_DIR) {
if (ent.type == UV_DIRENT_DIR)
{
tf_ssb_import(import->ssb, import->user, path);
} else {
}
else
{
size_t size = sizeof(tf_import_file_t) + strlen(import->parent) +1 + strlen(ent.name) + 1;
tf_import_file_t* file = malloc(size);
memset(file, 0, size);
@ -96,7 +105,8 @@ static void _tf_ssb_import_scandir(uv_fs_t* req)
import->work_left++;
int r = uv_fs_open(tf_ssb_get_loop(import->ssb), &file->req, path, 0, 0, _tf_ssb_import_file_open);
if (r < 0) {
if (r < 0)
{
printf("Failed to open %s: %s.\n", path, uv_strerror(r));
free(file);
import->work_left--;
@ -117,11 +127,13 @@ void tf_ssb_import(tf_ssb_t* ssb, const char* user, const char* path)
};
import.req.data = &import;
int r = uv_fs_scandir(tf_ssb_get_loop(ssb), &import.req, path, 0, _tf_ssb_import_scandir);
if (r) {
if (r)
{
printf("Failed to scan directory %s: %s.", path, uv_strerror(r));
}
while (import.work_left > 0) {
while (import.work_left > 0)
{
uv_run(tf_ssb_get_loop(ssb), UV_RUN_ONCE);
}
uv_fs_req_cleanup(&import.req);

View File

@ -19,9 +19,11 @@ static JSValue _tf_ssb_whoami(JSContext* context, JSValueConst this_val, int arg
{
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
printf("WHOAMI on %p\n", ssb);
if (ssb) {
if (ssb)
{
char id[512];
if (tf_ssb_whoami(ssb, id, sizeof(id))) {
if (tf_ssb_whoami(ssb, id, sizeof(id)))
{
return JS_NewString(context, id);
}
}
@ -32,13 +34,15 @@ static JSValue _tf_ssb_getMessage(JSContext* context, JSValueConst this_val, int
{
JSValue result = JS_NULL;
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
const char* id = JS_ToCString(context, argv[0]);
int64_t sequence = 0;
JS_ToInt64(context, &sequence, argv[1]);
int64_t timestamp = -1;
char* contents = NULL;
if (tf_ssb_db_get_message_by_author_and_sequence(ssb, id, sequence, NULL, 0, &timestamp, &contents)) {
if (tf_ssb_db_get_message_by_author_and_sequence(ssb, id, sequence, NULL, 0, &timestamp, &contents))
{
result = JS_NewObject(context);
JS_SetPropertyStr(context, result, "timestamp", JS_NewInt64(context, timestamp));
JS_SetPropertyStr(context, result, "content", JS_NewString(context, contents));
@ -53,11 +57,13 @@ static JSValue _tf_ssb_blobGet(JSContext* context, JSValueConst this_val, int ar
{
JSValue result = JS_NULL;
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
const char* id = JS_ToCString(context, argv[0]);
uint8_t* blob = NULL;
size_t size = 0;
if (tf_ssb_db_blob_get(ssb, id, &blob, &size)) {
if (tf_ssb_db_blob_get(ssb, id, &blob, &size))
{
result = JS_NewArrayBufferCopy(context, blob, size);
free(blob);
}
@ -70,18 +76,24 @@ static JSValue _tf_ssb_blobStore(JSContext* context, JSValueConst this_val, int
{
JSValue result = JS_NULL;
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
uint8_t* blob = NULL;
size_t size = 0;
char id[512];
if (JS_IsString(argv[0])) {
if (JS_IsString(argv[0]))
{
const char* text = JS_ToCStringLen(context, &size, argv[0]);
if (tf_ssb_db_blob_store(ssb, (const uint8_t*)text, size, id, sizeof(id))) {
if (tf_ssb_db_blob_store(ssb, (const uint8_t*)text, size, id, sizeof(id)))
{
result = JS_NewString(context, id);
}
JS_FreeCString(context, text);
} else if ((blob = tf_try_get_array_buffer(context, &size, argv[0])) != 0) {
if (tf_ssb_db_blob_store(ssb, blob, size, id, sizeof(id))) {
}
else if ((blob = tf_try_get_array_buffer(context, &size, argv[0])) != 0)
{
if (tf_ssb_db_blob_store(ssb, blob, size, id, sizeof(id)))
{
result = JS_NewString(context, id);
}
}
@ -93,11 +105,13 @@ static JSValue _tf_ssb_messageContentGet(JSContext* context, JSValueConst this_v
{
JSValue result = JS_NULL;
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
const char* id = JS_ToCString(context, argv[0]);
uint8_t* blob = NULL;
size_t size = 0;
if (tf_ssb_db_message_content_get(ssb, id, &blob, &size)) {
if (tf_ssb_db_message_content_get(ssb, id, &blob, &size))
{
result = JS_NewArrayBufferCopy(context, blob, size);
free(blob);
}
@ -110,12 +124,15 @@ static JSValue _tf_ssb_connections(JSContext* context, JSValueConst this_val, in
{
JSValue result = JS_NULL;
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
const char** connections = tf_ssb_get_connection_ids(ssb);
if (connections) {
if (connections)
{
result = JS_NewArray(context);
uint32_t i = 0;
for (const char** p = connections; *p; p++, i++) {
for (const char** p = connections; *p; p++, i++)
{
JS_SetPropertyUint32(context, result, i, JS_NewString(context, *p));
}
free(connections);
@ -132,7 +149,8 @@ static void _check_call(JSContext* context, JSValue result)
printf("ERROR: %s\n", value);
JS_FreeCString(context, value);
JSValue stack = JS_GetPropertyStr(context, result, "stack");
if (!JS_IsUndefined(stack)) {
if (!JS_IsUndefined(stack))
{
const char* stack_str = JS_ToCString(context, stack);
printf("%s\n", stack_str);
JS_FreeCString(context, stack_str);
@ -157,7 +175,8 @@ typedef struct _sqlStream_callback_t
JSValue callback;
} sqlStream_callback_t;
static void _tf_ssb_sqlStream_callback(JSValue row, void* user_data) {
static void _tf_ssb_sqlStream_callback(JSValue row, void* user_data)
{
sqlStream_callback_t* info = user_data;
JSValue response = JS_Call(info->context, info->callback, JS_UNDEFINED, 1, &row);
_check_call(info->context, response);
@ -171,9 +190,11 @@ static void _tf_ssb_sqlStream_callback(JSValue row, void* user_data) {
static JSValue _tf_ssb_sqlStream(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
const char* query = JS_ToCString(context, argv[0]);
if (query) {
if (query)
{
sqlStream_callback_t info = {
.context = context,
.callback = argv[2],
@ -188,9 +209,11 @@ static JSValue _tf_ssb_sqlStream(JSContext* context, JSValueConst this_val, int
static JSValue _tf_ssb_post(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
const char* post_text = JS_ToCString(context, argv[0]);
if (post_text) {
if (post_text)
{
tf_ssb_append_post(ssb, post_text);
JS_FreeCString(context, post_text);
}
@ -201,7 +224,8 @@ static JSValue _tf_ssb_post(JSContext* context, JSValueConst this_val, int argc,
static JSValue _tf_ssb_appendMessage(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
tf_ssb_append_message(ssb, argv[0]);
}
return JS_NULL;
@ -213,9 +237,12 @@ static JSValue _tf_ssb_storeMessage(JSContext* context, JSValueConst this_val, i
char signature[crypto_sign_BYTES + 128];
char id[crypto_hash_sha256_BYTES * 2 + 1];
tf_ssb_calculate_message_id(context, argv[0], id, sizeof(id));
if (tf_ssb_verify_and_strip_signature(context, argv[0], signature, sizeof(signature))) {
if (tf_ssb_verify_and_strip_signature(context, argv[0], signature, sizeof(signature)))
{
tf_ssb_db_store_message(ssb, context, id, argv[0], signature);
} else {
}
else
{
printf("failed to verify message\n");
}
return JS_UNDEFINED;
@ -246,7 +273,8 @@ static JSValue _tf_ssb_getBroadcasts(JSContext* context, JSValueConst this_val,
{
JSValue result = JS_UNDEFINED;
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (ssb)
{
result = JS_NewArray(context);
broadcasts_t broadcasts = {
.context = context,
@ -262,13 +290,17 @@ static JSValue _tf_ssb_connect(JSContext* context, JSValueConst this_val, int ar
{
JSValue args = argv[0];
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
if (JS_IsString(args)) {
if (ssb)
{
if (JS_IsString(args))
{
const char* address_str = JS_ToCString(context, args);
printf("Connecting to %s\n", address_str);
tf_ssb_connect_str(ssb, address_str);
JS_FreeCString(context, address_str);
} else {
}
else
{
JSValue address = JS_GetPropertyStr(context, args, "address");
JSValue port = JS_GetPropertyStr(context, args, "port");
JSValue pubkey = JS_GetPropertyStr(context, args, "pubkey");
@ -296,7 +328,8 @@ static void _tf_ssb_call_callback(tf_ssb_t* ssb, const char* name, void* user_da
JSValue global = JS_GetGlobalObject(context);
JSValue ssbo = JS_GetPropertyStr(context, global, "ssb");
JSValue callback = JS_GetPropertyStr(context, ssbo, name);
if (JS_IsFunction(context, callback)) {
if (JS_IsFunction(context, callback))
{
JSValue args = JS_UNDEFINED;
JSValue response = JS_Call(context, callback, JS_UNDEFINED, 0, &args);
_check_call(context, response);
@ -358,7 +391,8 @@ static JSValue _tf_ssb_rpc_send_binary(JSContext* context, JSValueConst this_val
size_t size;
uint8_t* message = tf_try_get_array_buffer(context, &size, argv[0]);
if (message) {
if (message)
{
tf_ssb_connection_rpc_send(
connection,
k_ssb_rpc_flag_binary | k_ssb_rpc_flag_stream,
@ -550,7 +584,8 @@ void tf_ssb_run_file(JSContext* context, const char* file_name)
printf("ERROR: %s\n", value);
JS_FreeCString(context, value);
JSValue stack = JS_GetPropertyStr(context, result, "stack");
if (!JS_IsUndefined(stack)) {
if (!JS_IsUndefined(stack))
{
const char* stack_str = JS_ToCString(context, stack);
printf("%s\n", stack_str);
JS_FreeCString(context, stack_str);
@ -568,12 +603,14 @@ void tf_ssb_run_file(JSContext* context, const char* file_name)
}
JSRuntime* runtime = JS_GetRuntime(context);
while (JS_IsJobPending(runtime)) {
while (JS_IsJobPending(runtime))
{
JSContext* context2 = NULL;
int r = JS_ExecutePendingJob(runtime, &context2);
JSValue result = JS_GetException(context2);
_check_call(context, result);
if (r == 0) {
if (r == 0)
{
break;
}
}
@ -582,11 +619,16 @@ void tf_ssb_run_file(JSContext* context, const char* file_name)
free(source);
}
JSValue _print(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
for (int i = 0; i < argc; ++i) {
if (JS_IsNull(argv[i])) {
JSValue _print(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
for (int i = 0; i < argc; ++i)
{
if (JS_IsNull(argv[i]))
{
printf(" null");
} else {
}
else
{
const char* value = JS_ToCString(context, argv[i]);
printf(" %s", value);
JS_FreeCString(context, value);
@ -596,27 +638,37 @@ JSValue _print(JSContext* context, JSValueConst this_val, int argc, JSValueConst
return JS_NULL;
}
static JSValue _utf8Decode(JSContext* context, uint8_t* data, size_t length) {
static JSValue _utf8Decode(JSContext* context, uint8_t* data, size_t length)
{
return JS_NewStringLen(context, (const char*)data, length);
}
static JSValue _utf8_decode(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _utf8_decode(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
JSValue result = JS_NULL;
size_t length;
if (JS_IsString(argv[0])) {
if (JS_IsString(argv[0]))
{
result = JS_DupValue(context, argv[0]);
} else {
}
else
{
uint8_t* array = tf_try_get_array_buffer(context, &length, argv[0]);
if (array) {
if (array)
{
result = _utf8Decode(context, array, length);
} else {
}
else
{
size_t offset;
size_t element_size;
JSValue buffer = tf_try_get_typed_array_buffer(context, argv[0], &offset, &length, &element_size);
size_t size;
if (!JS_IsException(buffer)) {
if (!JS_IsException(buffer))
{
array = tf_try_get_array_buffer(context, &size, buffer);
if (array) {
if (array)
{
result = _utf8Decode(context, array, size);
}
}
@ -629,10 +681,12 @@ static JSValue _utf8_decode(JSContext* context, JSValueConst this_val, int argc,
void tf_ssb_init(JSContext* context, tf_ssb_t* ssb)
{
JS_NewClassID(&_tf_ssb_classId);
JSClassDef def = {
JSClassDef def =
{
.class_name = "ssb",
};
if (JS_NewClass(JS_GetRuntime(context), _tf_ssb_classId, &def) != 0) {
if (JS_NewClass(JS_GetRuntime(context), _tf_ssb_classId, &def) != 0)
{
fprintf(stderr, "Failed to register ssb.\n");
}

View File

@ -37,15 +37,19 @@ static void _ssb_test_connections_changed(tf_ssb_t* ssb, tf_ssb_change_t change,
int count = 0;
const char** c = tf_ssb_get_connection_ids(ssb);
for (const char** p = c; *p; p++) {
for (const char** p = c; *p; p++)
{
count++;
}
free(c);
if (ssb == test->ssb0) {
if (ssb == test->ssb0)
{
printf("callback0 change=%d connection=%p\n", change, connection);
test->connection_count0 = count;
} else if (ssb == test->ssb1) {
}
else if (ssb == test->ssb1)
{
printf("callback1 change=%d connection=%p\n", change, connection);
test->connection_count1 = count;
}
@ -131,17 +135,20 @@ void tf_ssb_test_ssb(const tf_test_options_t* options)
tf_ssb_connect(ssb1, "127.0.0.1", 12347, id0bin);
while (test.connection_count0 != 1 ||
test.connection_count1 != 1) {
test.connection_count1 != 1)
{
uv_run(&loop, UV_RUN_ONCE);
}
tf_ssb_server_close(ssb0);
while (_ssb_test_count_messages(ssb1) < 3) {
while (_ssb_test_count_messages(ssb1) < 3)
{
uv_run(&loop, UV_RUN_ONCE);
}
printf("waiting for blob\n");
while (!tf_ssb_db_blob_get(ssb1, blob_id, NULL, NULL)) {
while (!tf_ssb_db_blob_get(ssb1, blob_id, NULL, NULL))
{
uv_run(&loop, UV_RUN_ONCE);
}
printf("done\n");
@ -202,16 +209,19 @@ void tf_ssb_test_following(const tf_test_options_t* options)
#define DUMP(id, depth)
#else
#define DUMP(id, depth) \
do { \
do \
{ \
printf("following %d:\n", depth); \
const char** tf_ssb_get_following_deep(tf_ssb_t* ssb_param, const char** ids, int depth_param); \
const char** f = tf_ssb_get_following_deep(ssb0, (const char*[]) { id, NULL }, depth); \
for (const char** p = f; p && *p; p++) { \
for (const char** p = f; p && *p; p++) \
{ \
printf("* %s\n", *p); \
} \
printf("\n"); \
free(f); \
} while (0)
} \
while (0)
#endif
FOLLOW(ssb0, id1, true);

File diff suppressed because it is too large Load Diff

View File

@ -38,9 +38,11 @@ typedef struct _tf_taskstub_t {
bool _finalized;
} tf_taskstub_t;
void tf_taskstub_startup() {
void tf_taskstub_startup()
{
static bool initialized;
if (!initialized) {
if (!initialized)
{
JS_NewClassID(&_classId);
size_t size = sizeof(_executable);
uv_exepath(_executable, &size);
@ -62,7 +64,8 @@ static JSValue _taskstub_loadFile(JSContext* context, JSValueConst this_val, int
static void _taskstub_on_process_exit(uv_process_t* process, int64_t status, int terminationSignal);
static void _taskstub_finalizer(JSRuntime *runtime, JSValue value);
static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_task_t* parent = tf_task_get(context);
tf_taskstub_t* stub = malloc(sizeof(tf_taskstub_t));
memset(stub, 0, sizeof(*stub));
@ -106,7 +109,8 @@ static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int a
JS_SetPropertyStr(context, taskObject, "loadFile", JS_NewCFunction(context, _taskstub_loadFile, "loadFile", 1));
taskid_t id = k_task_parent_id;
if (parent) {
if (parent)
{
id = tf_task_allocate_task_id(parent, (tf_taskstub_t*)stub);
}
stub->_id = id;
@ -116,7 +120,8 @@ static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int a
uv_pipe_t* pipe = tf_packetstream_get_pipe(stub->_stream);
memset(pipe, 0, sizeof(*pipe));
if (uv_pipe_init(tf_task_get_loop(parent), pipe, 1) != 0) {
if (uv_pipe_init(tf_task_get_loop(parent), pipe, 1) != 0)
{
fprintf(stderr, "uv_pipe_init failed\n");
}
@ -138,55 +143,67 @@ static JSValue _taskstub_create(JSContext* context, JSValueConst this_val, int a
JSValue result = JS_NULL;
stub->_process.data = stub;
int spawn_result = uv_spawn(tf_task_get_loop(parent), &stub->_process, &options);
if (spawn_result == 0) {
if (spawn_result == 0)
{
tf_packetstream_set_on_receive(stub->_stream, tf_task_on_receive_packet, stub);
tf_packetstream_start(stub->_stream);
result = taskObject;
} else {
}
else
{
fprintf(stderr, "uv_spawn failed: %s\n", uv_strerror(spawn_result));
JS_FreeValue(context, taskObject);
}
return result;
}
void _taskstub_gc_mark(JSRuntime* rt, JSValueConst value, JS_MarkFunc mark_func) {
void _taskstub_gc_mark(JSRuntime* rt, JSValueConst value, JS_MarkFunc mark_func)
{
tf_taskstub_t* stub = JS_GetOpaque(value, _classId);
if (stub) {
if (stub)
{
JS_MarkValue(rt, stub->_on_exit, mark_func);
JS_MarkValue(rt, stub->_on_error, mark_func);
}
}
JSValue tf_taskstub_init(JSContext* context) {
JSValue tf_taskstub_init(JSContext* context)
{
JSClassDef def = {
.class_name = "TaskStub",
.finalizer = &_taskstub_finalizer,
.gc_mark = _taskstub_gc_mark,
};
if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0) {
if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0)
{
fprintf(stderr, "Failed to register TaskStub class.\n");
}
return JS_NewCFunction2(context, _taskstub_create, "TaskStub", 0, JS_CFUNC_constructor, 0);
}
taskid_t tf_taskstub_get_id(const tf_taskstub_t* stub) {
taskid_t tf_taskstub_get_id(const tf_taskstub_t* stub)
{
return stub->_id;
}
JSValue tf_taskstub_get_task_object(const tf_taskstub_t* stub) {
JSValue tf_taskstub_get_task_object(const tf_taskstub_t* stub)
{
return stub->_taskObject;
}
tf_packetstream_t* tf_taskstub_get_stream(const tf_taskstub_t* stub) {
tf_packetstream_t* tf_taskstub_get_stream(const tf_taskstub_t* stub)
{
return stub->_stream;
}
tf_task_t* tf_taskstub_get_owner(const tf_taskstub_t* stub) {
tf_task_t* tf_taskstub_get_owner(const tf_taskstub_t* stub)
{
return stub->_owner;
}
tf_taskstub_t* tf_taskstub_create_parent(tf_task_t* task, uv_file file) {
tf_taskstub_t* tf_taskstub_create_parent(tf_task_t* task, uv_file file)
{
JSValue parentObject = JS_NewObject(tf_task_get_context(task));
tf_taskstub_t* parentStub = malloc(sizeof(tf_taskstub_t));
memset(parentStub, 0, sizeof(tf_taskstub_t));
@ -200,11 +217,13 @@ tf_taskstub_t* tf_taskstub_create_parent(tf_task_t* task, uv_file file) {
parentStub->_id = k_task_parent_id;
parentStub->_object = JS_DupValue(tf_task_get_context(task), parentObject);
if (uv_pipe_init(tf_task_get_loop(task), tf_packetstream_get_pipe(parentStub->_stream), 1) != 0) {
if (uv_pipe_init(tf_task_get_loop(task), tf_packetstream_get_pipe(parentStub->_stream), 1) != 0)
{
fprintf(stderr, "uv_pipe_init failed\n");
}
tf_packetstream_set_on_receive(parentStub->_stream, tf_task_on_receive_packet, parentStub);
if (uv_pipe_open(tf_packetstream_get_pipe(parentStub->_stream), file) != 0) {
if (uv_pipe_open(tf_packetstream_get_pipe(parentStub->_stream), file) != 0)
{
fprintf(stderr, "uv_pipe_open failed\n");
}
tf_packetstream_start(parentStub->_stream);
@ -216,12 +235,14 @@ static void _taskstub_cleanup(tf_taskstub_t* stub)
{
if (!stub->_process.data &&
JS_IsUndefined(stub->_object) &&
stub->_finalized) {
stub->_finalized)
{
free(stub);
}
}
static void _taskstub_finalizer(JSRuntime* runtime, JSValue value) {
static void _taskstub_finalizer(JSRuntime* runtime, JSValue value)
{
tf_taskstub_t* stub = JS_GetOpaque(value, _classId);
stub->_on_exit = JS_UNDEFINED;
stub->_on_error = JS_UNDEFINED;
@ -240,10 +261,12 @@ static void _taskstub_on_handle_close(uv_handle_t* handle)
_taskstub_cleanup(stub);
}
static void _taskstub_on_process_exit(uv_process_t* process, int64_t status, int terminationSignal) {
static void _taskstub_on_process_exit(uv_process_t* process, int64_t status, int terminationSignal)
{
tf_taskstub_t* stub = process->data;
JSContext* context = tf_task_get_context(stub->_owner);
if (!JS_IsUndefined(stub->_on_exit)) {
if (!JS_IsUndefined(stub->_on_exit))
{
JSValue argv[] = { JS_NewInt32(context, status), JS_NewInt32(context, terminationSignal) };
JSValue result = JS_Call(context, stub->_on_exit, JS_NULL, 2, argv);
tf_task_report_error(stub->_owner, result);
@ -257,14 +280,16 @@ static void _taskstub_on_process_exit(uv_process_t* process, int64_t status, int
tf_taskstub_destroy(stub);
}
static JSValue _taskstub_getExports(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_getExports(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
promiseid_t promise = tf_task_allocate_promise(stub->_owner);
tf_task_send_promise_message(stub->_owner, (tf_taskstub_t*)stub, kGetExports, promise, JS_UNDEFINED);
return tf_task_get_promise(stub->_owner, promise);
}
static JSValue _taskstub_setImports(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_setImports(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
void* buffer;
size_t size;
@ -273,7 +298,8 @@ static JSValue _taskstub_setImports(JSContext* context, JSValueConst this_val, i
return JS_UNDEFINED;
}
static JSValue _taskstub_setRequires(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_setRequires(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
void* buffer;
size_t size;
@ -282,7 +308,8 @@ static JSValue _taskstub_setRequires(JSContext* context, JSValueConst this_val,
return JS_UNDEFINED;
}
static JSValue _taskstub_loadFile(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_loadFile(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
void* buffer;
size_t size;
@ -291,57 +318,69 @@ static JSValue _taskstub_loadFile(JSContext* context, JSValueConst this_val, int
return JS_UNDEFINED;
}
static JSValue _taskstub_get_on_exit(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_get_on_exit(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
return JS_DupValue(context, stub->_on_exit);
}
static JSValue _taskstub_set_on_exit(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_set_on_exit(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
if (!JS_IsUndefined(stub->_on_exit)) {
if (!JS_IsUndefined(stub->_on_exit))
{
JS_FreeValue(context, stub->_on_exit);
}
stub->_on_exit = JS_DupValue(context, argv[0]);
return JS_UNDEFINED;
}
static JSValue _taskstub_get_on_error(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_get_on_error(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
return JS_DupValue(context, stub->_on_error);
}
static JSValue _taskstub_set_on_error(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_set_on_error(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
if (!JS_IsUndefined(stub->_on_error)) {
if (!JS_IsUndefined(stub->_on_error))
{
JS_FreeValue(context, stub->_on_error);
}
stub->_on_error = JS_DupValue(context, argv[0]);
return JS_UNDEFINED;
}
static JSValue _taskstub_activate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_activate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
if (stub) {
if (stub)
{
tf_packetstream_send(stub->_stream, kActivate, 0, 0);
}
return JS_NULL;
}
static JSValue _taskstub_execute(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_execute(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
promiseid_t promise = tf_task_allocate_promise(stub->_owner);
tf_task_send_promise_message(stub->_owner, (tf_taskstub_t*)stub, kExecute, promise, argv[0]);
return tf_task_get_promise(stub->_owner, promise);
}
static JSValue _taskstub_kill(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
static JSValue _taskstub_kill(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_taskstub_t* stub = JS_GetOpaque(this_val, _classId);
uv_process_kill(&stub->_process, SIGTERM);
return JS_UNDEFINED;
}
void tf_taskstub_destroy(tf_taskstub_t* stub) {
if (!JS_IsUndefined(stub->_object)) {
void tf_taskstub_destroy(tf_taskstub_t* stub)
{
if (!JS_IsUndefined(stub->_object))
{
JSValue object = stub->_object;
stub->_object = JS_UNDEFINED;
JS_FreeValue(tf_task_get_context(stub->_owner), object);
@ -351,7 +390,8 @@ void tf_taskstub_destroy(tf_taskstub_t* stub) {
void tf_taskstub_on_error(tf_taskstub_t* stub, JSValue error)
{
JSContext* context = tf_task_get_context(stub->_owner);
if (!JS_IsUndefined(stub->_on_error)) {
if (!JS_IsUndefined(stub->_on_error))
{
JSValue result = JS_Call(context, stub->_on_error, JS_NULL, 1, &error);
tf_task_report_error(stub->_owner, result);
JS_FreeValue(context, result);

View File

@ -513,12 +513,15 @@ static void _test_file(const tf_test_options_t* options)
static void _tf_test_run(const tf_test_options_t* options, const char* name, void (*test)(const tf_test_options_t* options))
{
bool specified = false;
if (options->tests) {
if (options->tests)
{
char* dup = strdup(options->tests);
char* state = NULL;
const char* t = NULL;
while ((t = strtok_r(t ? NULL : dup, ",", &state)) != NULL) {
if (strcmp(t, name) == 0) {
while ((t = strtok_r(t ? NULL : dup, ",", &state)) != NULL)
{
if (strcmp(t, name) == 0)
{
specified = true;
break;
}
@ -526,7 +529,8 @@ static void _tf_test_run(const tf_test_options_t* options, const char* name, voi
free(dup);
}
if (!options->tests || specified) {
if (!options->tests || specified)
{
printf("Running test %s.\n", name);
test(options);
printf("[\e[1;32mpass\e[0m] %s\n", name);

633
src/tls.c

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,8 @@ static JSValue _tls_context_wrapper_add_trusted_certificate(JSContext* context,
static JSValue _tls_context_wrapper_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
static void _tls_context_wrapper_finalizer(JSRuntime *runtime, JSValue value);
JSValue _tls_context_wrapper_set_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _tls_context_wrapper_set_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(this_val, _classId);
const char* value = JS_ToCString(context, argv[0]);
tf_tls_context_set_certificate(wrapper->context, value);
@ -31,7 +32,8 @@ JSValue _tls_context_wrapper_set_certificate(JSContext* context, JSValueConst th
return JS_UNDEFINED;
}
JSValue _tls_context_wrapper_set_private_key(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _tls_context_wrapper_set_private_key(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(this_val, _classId);
const char* value = JS_ToCString(context, argv[0]);
tf_tls_context_set_private_key(wrapper->context, value);
@ -39,7 +41,8 @@ JSValue _tls_context_wrapper_set_private_key(JSContext* context, JSValueConst th
return JS_UNDEFINED;
}
JSValue _tls_context_wrapper_add_trusted_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _tls_context_wrapper_add_trusted_certificate(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(this_val, _classId);
const char* value = JS_ToCString(context, argv[0]);
tf_tls_context_add_trusted_certificate(wrapper->context, value);
@ -47,28 +50,34 @@ JSValue _tls_context_wrapper_add_trusted_certificate(JSContext* context, JSValue
return JS_UNDEFINED;
}
JSValue tf_tls_context_wrapper_init(JSContext* context) {
JSValue tf_tls_context_wrapper_init(JSContext* context)
{
JS_NewClassID(&_classId);
JSClassDef def = {
JSClassDef def =
{
.class_name = "TlsContext",
.finalizer = _tls_context_wrapper_finalizer,
};
if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0) {
if (JS_NewClass(JS_GetRuntime(context), _classId, &def) != 0)
{
fprintf(stderr, "Failed to register TlsContext.\n");
}
return JS_NewCFunction2(context, _tls_context_wrapper_create, "TlsContext", 0, JS_CFUNC_constructor, 0);
}
tf_tls_context_t* tf_tls_context_wrapper_get(JSValue value) {
tf_tls_context_t* tf_tls_context_wrapper_get(JSValue value)
{
tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(value, _classId);
return wrapper ? wrapper->context : NULL;
}
int tf_tls_context_wrapper_get_count() {
int tf_tls_context_wrapper_get_count()
{
return _count;
}
JSValue _tls_context_wrapper_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) {
JSValue _tls_context_wrapper_create(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_tls_context_wrapper_t* wrapper = malloc(sizeof(tf_tls_context_wrapper_t));
memset(wrapper, 0, sizeof(*wrapper));
@ -86,9 +95,11 @@ JSValue _tls_context_wrapper_create(JSContext* context, JSValueConst this_val, i
return wrapper->object;
}
void _tls_context_wrapper_finalizer(JSRuntime *runtime, JSValue value) {
void _tls_context_wrapper_finalizer(JSRuntime *runtime, JSValue value)
{
tf_tls_context_wrapper_t* wrapper = JS_GetOpaque(value, _classId);
if (wrapper->context) {
if (wrapper->context)
{
tf_tls_context_destroy(wrapper->context);
wrapper->context = NULL;
}

View File

@ -34,7 +34,8 @@ static int64_t _trace_ts()
{
int64_t result = 0;
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
{
result = (ts.tv_sec * 1e9 + ts.tv_nsec) / 1e3;
}
return result;
@ -42,12 +43,14 @@ static int64_t _trace_ts()
static void _trace_append(tf_trace_t* trace, const char* buffer, size_t size)
{
if (trace->write_offset + size >= k_buffer_size) {
if (trace->write_offset + size >= k_buffer_size)
{
trace->buffer[trace->write_offset] = '\0';
trace->write_offset = 0;
}
if (trace->write_offset + size < k_buffer_size) {
if (trace->write_offset + size < k_buffer_size)
{
memcpy(trace->buffer + trace->write_offset, buffer, size);
trace->write_offset += size;
trace->buffer[trace->write_offset++] = '\n';
@ -56,7 +59,8 @@ static void _trace_append(tf_trace_t* trace, const char* buffer, size_t size)
void tf_trace_counter(tf_trace_t* trace, const char* name, int argc, const char** arg_names, const int64_t* arg_values)
{
if (!trace) {
if (!trace)
{
return;
}
@ -73,18 +77,22 @@ void tf_trace_counter(tf_trace_t* trace, const char* name, int argc, const char*
void tf_trace_begin(tf_trace_t* trace, const char* name)
{
if (!trace) {
if (!trace)
{
return;
}
char line[1024];
int p = snprintf(line, sizeof(line), "{\"ph\": \"B\", \"pid\": %d, \"ts\": %" PRId64 ", \"name\": \"", getpid(), _trace_ts());
for (const char* c = name; *c && p < (int)sizeof(line); c++) {
switch (*c) {
for (const char* c = name; *c && p < (int)sizeof(line); c++)
{
switch (*c)
{
case '"':
case '\\':
line[p++] = '\\';
if (p < (int)sizeof(line)) {
if (p < (int)sizeof(line))
{
line[p++] = *c;
}
break;
@ -99,7 +107,8 @@ void tf_trace_begin(tf_trace_t* trace, const char* name)
void tf_trace_end(tf_trace_t* trace)
{
if (!trace) {
if (!trace)
{
return;
}
@ -110,7 +119,8 @@ void tf_trace_end(tf_trace_t* trace)
char* tf_trace_export(tf_trace_t* trace)
{
if (!trace) {
if (!trace)
{
return NULL;
}
@ -120,14 +130,16 @@ char* tf_trace_export(tf_trace_t* trace)
int begin = newline ? newline - trace->buffer : 0;
size_t size = 0;
size += snprintf(buffer, k_buffer_size, "{\"displayTimeUnit\": \"ns\",\n\"traceEvents\": [\n");
if (begin) {
if (begin)
{
size_t this_size = strlen(trace->buffer + begin);
memcpy(buffer + size, trace->buffer + begin, this_size);
size += this_size;
}
memcpy(buffer + size, trace->buffer, trace->write_offset);
size += trace->write_offset;
if (size > 2 && buffer[size - 1] == '\n' && buffer[size - 2] == ',') {
if (size > 2 && buffer[size - 1] == '\n' && buffer[size - 2] == ',')
{
buffer[size - 2] = '\n';
size--;
}
@ -140,11 +152,13 @@ char* tf_trace_export(tf_trace_t* trace)
static int _tf_trace_sqlite_callback(unsigned int t, void* c, void* p, void* x)
{
tf_trace_t* trace = c;
switch (t) {
switch (t)
{
case SQLITE_TRACE_STMT:
{
const char* statement = x;
if (statement[0] != '-' || statement[1] != '-') {
if (statement[0] != '-' || statement[1] != '-')
{
tf_trace_begin(trace, statement);
}
}
@ -158,9 +172,12 @@ static int _tf_trace_sqlite_callback(unsigned int t, void* c, void* p, void* x)
void tf_trace_sqlite(tf_trace_t* trace, sqlite3* sqlite)
{
if (sqlite) {
if (sqlite)
{
sqlite3_trace_v2(sqlite, SQLITE_TRACE_STMT | SQLITE_TRACE_PROFILE, _tf_trace_sqlite_callback, trace);
} else {
}
else
{
sqlite3_trace_v2(sqlite, 0, NULL, NULL);
}
}