Skip to content

Commit

Permalink
Land extension fixes (#518)
Browse files Browse the repository at this point in the history
* refactor(src/extension): improve init state and context tree

* refactor(src/cli): allow building jsut an extension

* refactor(src): clean up / tidy

* refactor(include/socket/extension.h): include 'sapi_context_alloc' prototype

* refactor(api): clean up, listen 'connect'() for dgram

* fix(extension): remove from 'init' list after deinit

* refactor(src/extension/extension.cc: use 'std::make_shared'

* fix(src/cli/templates.hh): remove 'v' prefix in 'CFBundleVersion'

* chore(api/index.d.ts): generate typings

* Fix spacing

---------

Co-authored-by: Joseph Werle <joseph.werle@gmail.com>
  • Loading branch information
bcomnes and jwerle committed Aug 14, 2023
1 parent 0e159f3 commit 15335af
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 35 deletions.
2 changes: 1 addition & 1 deletion api/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ export class Socket extends EventEmitter {
constructor (options, callback) {
super()

this.id = rand64()
this.id = options?.id || rand64()

if (typeof options === 'string') {
options = { type: options }
Expand Down
6 changes: 3 additions & 3 deletions api/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ export class Extension extends EventTarget {
/**
* Load an extension by name.
* @param {string} name
* @param {{ features: string[] | string ?} [options]
* @param {{ allow: string[] | string ?} [options]
* @return {Promise<Extension>}
*/
static async load (name, options) {
options = { name, ...options }

if (Array.isArray(options.features)) {
options.features = options.features.join(',')
if (Array.isArray(options.allow)) {
options.allow = options.allow.join(',')
}

const result = await ipc.request('extension.load', options)
Expand Down
4 changes: 2 additions & 2 deletions api/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3609,7 +3609,7 @@ declare module "socket:dgram" {
*/
export class Socket extends EventEmitter {
constructor(options: any, callback: any);
id: bigint;
id: any;
type: any;
signal: any;
state: {
Expand Down Expand Up @@ -3871,7 +3871,7 @@ declare module "socket:extension" {
/**
* Load an extension by name.
* @param {string} name
* @param {{ features: string[] | string ?} [options]
* @param {{ allow: string[] | string ?} [options]
* @return {Promise<Extension>}
*/
static load(name: string, options: any): Promise<Extension>;
Expand Down
4 changes: 4 additions & 0 deletions api/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,10 @@ export function parseJSON (string) {
}

export function parseHeaders (headers) {
if (Array.isArray(headers)) {
headers = headers.map((h) => h.trim()).join('\n')
}

if (typeof headers !== 'string') {
return []
}
Expand Down
31 changes: 29 additions & 2 deletions include/socket/extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,18 @@ extern "C" {
/**
* Get a context error location.
* @param context - An extension context
* @preturn The location of the error
* @return The location of the error
*/
SOCKET_RUNTIME_EXTENSION_EXPORT
const char* sapi_context_error_get_location (const sapi_context_t* context);

/**
* @param context - An extension context
* @return Allocated memmory for the context
*/
SOCKET_RUNTIME_EXTENSION_EXPORT
void* sapi_context_alloc (sapi_context_t* context, unsigned int size);


/**
* JavaScript API
Expand All @@ -315,7 +322,7 @@ extern "C" {
* @param source - The source of the script to evaluate
*/
SOCKET_RUNTIME_EXTENSION_EXPORT
void sapi_evaluate_javascript (
void sapi_javascript_evaluate (
sapi_context_t* context,
const char* name,
const char* source
Expand Down Expand Up @@ -782,6 +789,26 @@ extern "C" {
const sapi_ipc_message_t* message
);

/**
* Get the buffer bytes associated with the IPC message.
* @param message The IPC message
* @return The IPC message va (possibly `NULL`)
*/
SOCKET_RUNTIME_EXTENSION_EXPORT
const unsigned char* sapi_ipc_message_get_bytes (
const sapi_ipc_message_t* message
);

/**
* Get the buffer bytes size associated with the IPC message.
* @param message The IPC message
* @return The IPC message va (possibly `NULL`)
*/
SOCKET_RUNTIME_EXTENSION_EXPORT
unsigned int sapi_ipc_message_get_bytes_size (
const sapi_ipc_message_t* message
);

/**
* Get the IPC message name.
* @param message The IPC message
Expand Down
30 changes: 26 additions & 4 deletions src/cli/cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,26 @@ int main (const int argc, const char* argv[]) {

settings = parseINI(ini);

if (settings["meta_type"] == "extension" || settings["build_type"] == "extension") {
auto extension = settings["build_name"];
settings["build_extensions_" + extension + "_path"] = fs::current_path().string();

for (const auto& entry : settings) {
if (entry.first.starts_with("extension_sources")) {
settings["build_extensions_" + extension] += entry.second;
} else if (entry.first.starts_with("extension_")) {
auto key = replace(entry.first, "extension_", extension + "_");
auto value = entry.second;
auto index = "build_extensions_" + key;
if (settings[index].size() > 0) {
settings[index] += " " + value;
} else {
settings[index] = value;
}
}
}
}

// allow for local `.sscrc` '[settings] ...' entries to overload the
// project's settings in `socket.ini`:
// [settings.ios]
Expand Down Expand Up @@ -2543,6 +2563,7 @@ int main (const int argc, const char* argv[]) {
}

bool isForDesktop = !flagBuildForIOS && !flagBuildForAndroid;
auto isForExtensionOnly = settings["meta_type"] == "extension" || settings["build_type"] == "extension";

if (isForDesktop) {
fs::create_directories(paths.platformSpecificOutputPath / "include");
Expand Down Expand Up @@ -4545,7 +4566,7 @@ int main (const int argc, const char* argv[]) {
} else if (source.ends_with(".o") || source.ends_with(".a")) {
objects << source << " ";
continue;
} else if (source.ends_with(".c")) {
} else if (source.ends_with(".c") || source.ends_with(".m")) {
compiler = CC.size() > 0 ? CC : "clang";
if (platform.mac) {
compilerFlags += " -ObjC -v";
Expand Down Expand Up @@ -4583,6 +4604,7 @@ int main (const int argc, const char* argv[]) {
<< (" -L" + quote + trim(prefixFile("lib/" + platform.arch + "-desktop")) + quote)
<< " -lsocket-runtime"
#endif
<< " -fvisibility=hidden"
<< " -DIOS=0"
// << " -U__CYGWIN__"
<< " -DANDROID=0"
Expand Down Expand Up @@ -4701,9 +4723,9 @@ int main (const int argc, const char* argv[]) {
<< " " << extraFlags
<< " -lsocket-runtime"
<< " -luv"
<< " -fvisibility=hidden"
<< (" -L" + quote + trim(prefixFile("lib/" + platform.arch + "-desktop")) + quote)
#endif
<< " -fvisibility=hidden"
<< " " << trim(linkerFlags + " " + (flagDebugMode ? linkerDebugFlags : ""))
<< (" -I" + quote + trim(prefixFile("include")) + quote)
<< (" -I" + quote + trim(prefixFile("src")) + quote)
Expand Down Expand Up @@ -4750,7 +4772,7 @@ int main (const int argc, const char* argv[]) {
fs::current_path(oldCwd);
}

if (flagRunUserBuildOnly == false && isForDesktop) {
if (flagRunUserBuildOnly == false && isForDesktop && !isForExtensionOnly) {
StringStream compileCommand;

// windows / spaces in bin path - https://stackoverflow.com/a/27976653/3739540
Expand Down Expand Up @@ -4832,7 +4854,7 @@ int main (const int argc, const char* argv[]) {
//
// MacOS Stripping
//
if (platform.mac && isForDesktop) {
if (platform.mac && isForDesktop && !isForExtensionOnly) {
StringStream stripCommand;

stripCommand
Expand Down
2 changes: 1 addition & 1 deletion src/cli/templates.hh
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ constexpr auto gPListInfo = R"XML(<?xml version="1.0" encoding="UTF-8"?>
<key>DTSDKBuild</key>
<string>10.13</string>
<key>CFBundleVersion</key>
<string>v{{meta_version}}</string>
<string>{{meta_version}}</string>
<key>BuildMachineOSBuild</key>
<string>17D102</string>
<key>NSCameraUsageDescription</key>
Expand Down
3 changes: 2 additions & 1 deletion src/core/core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ namespace SSC {
"const headers = `" + trim(post.headers) + "` \n"
" .trim() \n"
" .split(/[\\r\\n]+/) \n"
" .filter(Boolean); \n"
" .filter(Boolean) \n"
" .map((header) => header.trim()); \n"
" \n"
"let params = `" + params + "`; \n"
" \n"
Expand Down
22 changes: 11 additions & 11 deletions src/extension/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,15 @@ sapi_context_t* sapi_context_create (
return nullptr;
}

auto context = retained || parent == nullptr
retained = retained || parent == nullptr;
auto context = retained
? new sapi_context_t(parent)
: parent->memory.alloc<sapi_context_t>();
: parent->memory.alloc<sapi_context_t>(parent, parent);

if (retained || parent == nullptr) {
context->retained = true;
}

if (parent != nullptr) {
context->context = parent;
context->extension = parent->extension;
context->router = parent->router;
context->config = parent->config;
context->data = parent->data;
context->policies = parent->policies;
}

return context;
}

Expand Down Expand Up @@ -195,3 +187,11 @@ void sapi_context_config_set (
if (context == nullptr || key == nullptr) return;
context->config[key] = value;
}

void* sapi_context_alloc (sapi_context_t* context, unsigned int size) {
if (context == nullptr || size == 0) {
return nullptr;
}

return reinterpret_cast<void*>(context->memory.alloc<unsigned char>(size));
}
29 changes: 27 additions & 2 deletions src/extension/extension.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace SSC {
static Extension::Map extensions = {};
static Vector<String> initializedExtensions;
static Mutex mutex;

static String getcwd () {
Expand Down Expand Up @@ -107,6 +108,7 @@ namespace SSC {
this->config = context.config;
this->data = context.data;
this->policies = context.policies;
this->internal = context.internal;
}

Extension::Context::Context (const Context* context) {
Expand All @@ -116,6 +118,7 @@ namespace SSC {
this->config = context->config;
this->data = context->data;
this->policies = context->policies;
this->internal = context->internal;
}
}

Expand All @@ -128,6 +131,7 @@ namespace SSC {
this->config = context.config;
this->data = context.data;
this->policies = context.policies;
this->internal = context.internal;
}

Extension::Context::Context (IPC::Router* router) : Context() {
Expand All @@ -148,6 +152,7 @@ namespace SSC {
}

void Extension::Context::setPolicy (const String& name, bool allowed) {
if (name.size() == 0) return;
if (this->hasPolicy(name)) {
auto policy = this->getPolicy(name);
policy.allowed = allowed;
Expand Down Expand Up @@ -406,7 +411,7 @@ namespace SSC {
return;
}

auto extension = std::shared_ptr<Extension>(new Extension(name, initializer));
auto extension = std::make_shared<Extension>(name, initializer);
extensions.insert_or_assign(name, extension);
}

Expand All @@ -421,11 +426,21 @@ namespace SSC {
return false;
}

if (std::count(initializedExtensions.begin(), initializedExtensions.end(), name) > 0) {
debug("Extension '%s' already loaded", name.c_str());
// already initializedExtensions
return true;
}

auto extension = extensions.at(name);
if (extension != nullptr && extension->initializer != nullptr) {
debug("Initializing loaded extension: %s", name.c_str());
extension->context.data = data;
return extension->initializer(ctx, data);
auto didInitialize = extension->initializer(ctx, data);
if (didInitialize) {
initializedExtensions.push_back(name);
}
return didInitialize;
}

return false;
Expand Down Expand Up @@ -457,6 +472,16 @@ bool sapi_extension_register (
auto deinitializer = registration->deinitializer;
if (deinitializer != nullptr) {
debug("Unloading extension: %s", registration->name);
auto initializedExtensionsCursor = std::find(
SSC::initializedExtensions.begin(),
SSC::initializedExtensions.end(),
SSC::String(registration->name)
);

if (initializedExtensionsCursor != SSC::initializedExtensions.end()) {
SSC::initializedExtensions.erase(initializedExtensionsCursor);
}

return deinitializer(reinterpret_cast<sapi_context_t*>(ctx), data);
}

Expand Down
25 changes: 19 additions & 6 deletions src/extension/ipc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ bool sapi_ipc_router_map (
message.buffer.bytes,
message.buffer.size
);
context->internal = context->memory.alloc<SSC::IPC::Router::ReplyCallback>(reply);
context->internal = new SSC::IPC::Router::ReplyCallback(reply);
callback(
context,
(sapi_ipc_message_t*) &msg,
Expand Down Expand Up @@ -127,10 +127,9 @@ bool sapi_ipc_reply (const sapi_ipc_result_t* result) {
auto fn = reinterpret_cast<SSC::IPC::Router::ReplyCallback*>(internal);

if (fn != nullptr) {
if (fn != nullptr && result != nullptr) {
(*fn)(*result);
success = true;
}
(*fn)(*result);
success = true;
delete fn;
}

// if retained, then then caller must eventually call `sapi_context_release()`
Expand Down Expand Up @@ -158,7 +157,7 @@ bool sapi_ipc_send_bytes (
.ttl = 0,
.body = new char[size]{0},
.length = size,
.headers =headers ? headers : ""
.headers = headers ? headers : ""
};

memcpy(post.body, bytes, size);
Expand Down Expand Up @@ -405,6 +404,20 @@ sapi_ipc_result_t* sapi_ipc_result_clone (
return context->memory.alloc<sapi_ipc_result_t>(context, *result);
}

const unsigned char* sapi_ipc_message_get_bytes (
const sapi_ipc_message_t* message
) {
if (!message) return nullptr;
return reinterpret_cast<const unsigned char*>(message->buffer.bytes);
}

unsigned int sapi_ipc_message_get_bytes_size (
const sapi_ipc_message_t* message
) {
if (!message || !message->buffer.bytes) return 0;
return static_cast<unsigned int>(message->buffer.size);
}

void sapi_ipc_result_set_seq (sapi_ipc_result_t* result, const char* seq) {
if (result && seq) {
result->seq = seq;
Expand Down
Loading

0 comments on commit 15335af

Please sign in to comment.