Skip to content

Commit

Permalink
Use ZeroMQ for IPC layer (#11)
Browse files Browse the repository at this point in the history
kasperisager authored Dec 6, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 6a5dc78 commit e18838a
Showing 34 changed files with 918 additions and 1,579 deletions.
7 changes: 2 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -5,20 +5,17 @@ find_package(cmake-bare-bundle REQUIRED PATHS node_modules/cmake-bare-bundle)
find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
find_package(cmake-npm REQUIRED PATHS node_modules/cmake-npm)

project(bare_kit LANGUAGES C VERSION 1.0)
project(bare_kit LANGUAGES C CXX VERSION 1.0)

include(overrides.cmake)

set(BARE_USE_SYSTEM_LOG ON CACHE BOOL "Use system logging" FORCE)

install_node_modules()

if(APPLE)
enable_language(OBJC)
endif()

fetch_package("github:holepunchto/bare@1.12.0")
fetch_package("github:holepunchto/librpc")
fetch_package("github:holepunchto/bare@1.12.2")

add_subdirectory(shared)

175 changes: 1 addition & 174 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,182 +1,9 @@
# bare-kit

Bare for native application development. The kit provides a web worker-like API to start and manage an isolated Bare thread, called a worklet[^1], that exposes an RPC abstraction with bindings for various languages.
Bare for native application development. The kit provides a web worker-like API to start and manage an isolated Bare thread, called a worklet[^1], that exposes an IPC abstraction with bindings for various languages.

[^1]: This term was chosen to avoid ambiguity with worker threads as implemented by <https://github.com/holepunchto/bare-worker>.

## Usage

### JavaScript

In this example we create a simple RPC instance using Bare Kit that sends a `ping` request, handles the request and outputs `pong` to the console.

Create a new RPC instance, providing a request handler

```js
const rpc = new BareKit.RPC((req) => {
if (req.command === 'ping') {
console.log(req.data.toString())

req.reply('pong')
}
})
```

Create an outgoing request with the command `ping`

```js
const req = rpc.request('ping')
```

Send the request with the data `ping`

```js
req.send('ping')
```

Store the received data and log it to console

```js
const data = await req.reply()
console.log(data.toString())
```

### iOS

In this example we create a simple RPC instance for iOS using Bare Kit and Objective-C that sends a `ping` request, handles the request and outputs `pong`.

Import the BareKit framework

```objc
#import <BareKit/BareKit.h>
```

Create a new Bare worklet instance

```objc
BareWorklet *worklet = [[BareWorklet alloc] init];
```

Start the worklet with the specified bundle source

```objc
[worklet start:@"/app.bundle" source:/* Source for `app.bundle` */];
```
Create an IPC instance associated with the worklet
```objc
BareIPC *ipc = [[BareIPC alloc] initWithWorklet:worklet];
```

Define a request handler block

```objc
BareRPCRequestHandler requestHandler = ^(BareRPCIncomingRequest *req, NSError *error) {
if ([req.command isEqualToString:@"ping"]) {
CFShow([req dataWithEncoding:NSUTF8StringEncoding]);

[req reply:@"pong" encoding:NSUTF8StringEncoding];
}
};
```

Create an RPC instance with the IPC and request handler

```objc
BareRPC *rpc = [[BareRPC alloc] initWithIPC:ipc requestHandler:requestHandler];
```
Create an outgoing request with the command `ping`
```objc
BareRPCOutgoingRequest *req = [rpc request:@"ping"];
```

Send the request with the data `ping`

```objc
[req send:@"ping" encoding:NSUTF8StringEncoding];
```
Get the reply data asynchronously and log the received data
```objc
[req reply:NSUTF8StringEncoding completion:^(NSString *data, NSError *error) {
CFShow(data);
}];
```

See <https://github.com/holepunchto/bare-ios> for a complete example of using the kit in an iOS application.

### Android

In this example we create a simple RPC instance for Android using Bare Kit and Java that sends a `ping` request, handles the request and outputs `pong`.

Import necessary classes from BareKit.

```java
import to.holepunch.bare.kit.IPC;
import to.holepunch.bare.kit.RPC;
import to.holepunch.bare.kit.Worklet;
```

Create a new worklet instance

```java
Worklet worklet = new Worklet();
```

Start the worklet, loading the bundle from assets

```java
try {
worklet.start("/app.bundle", getAssets().open("app.bundle"));
} catch (Exception e) {
throw new RuntimeException(e);
}
```

Create an IPC instance using the worklet

```java
IPC ipc = new IPC(worklet);
```

Create an RPC instance with the IPC and a request handler

```java
RPC rpc = new RPC(ipc, (req, error) -> {
if (req.command.equals("ping")) {
Log.i(TAG, req.data("UTF-8"));

req.reply("pong", "UTF-8");
}
});
```

Create an outgoing request with command "ping"

```java
RPC.OutgoingRequest req = rpc.request("ping");
```

Send the request with data "ping"

```java
req.send("ping", "UTF-8");
```

Get the reply data asynchronously and log the received data

```java
req.reply("UTF-8", (data, error) -> {
Log.i(TAG, data);
});
```

See <https://github.com/holepunchto/bare-android> for a complete example of using the kit in an Android application.

## License

Apache-2.0
5 changes: 3 additions & 2 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -11,13 +11,14 @@ set_target_properties(
target_sources(
bare_kit
PRIVATE
src/main/jni/IPC.c
src/main/jni/Worklet.c
)

target_link_libraries(
bare_kit
PRIVATE
android
PUBLIC
bare_worklet
PRIVATE
nativehelper # For `java.io.FileDescriptor` APIs
)
8 changes: 6 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ android {
ndkVersion "27.2.12479018"

defaultConfig {
minSdk 31
minSdk 28
targetSdk 34

externalNativeBuild {
@@ -19,6 +19,8 @@ android {
arguments "-DDRIVE_CORESTORE_DIR=build/_drive", "-DANDROID_STL=c++_shared"
}
}

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

externalNativeBuild {
@@ -31,11 +33,13 @@ android {
packagingOptions {
jniLibs {
excludes.add("**/libuv.so")
excludes.add("**/libc++_shared.so")
}
}
}

dependencies {
api "com.google.firebase:firebase-messaging:+"

androidTestImplementation "androidx.test:runner:+"
androidTestImplementation "androidx.test:rules:+"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package to.holepunch.bare.kit;

import android.os.Looper;
import android.util.Log;
import java.nio.charset.StandardCharsets;
import org.junit.Test;

public class WorkletTest {
@Test
public void
CreateWorklet() {
Worklet worklet = new Worklet(null);

worklet.start("/app.js", "BareKit.IPC.on('data', (data) => BareKit.IPC.write(data)).write('Hello!')", StandardCharsets.UTF_8, null);

Looper.prepare();

Looper looper = Looper.myLooper();

IPC ipc = new IPC(worklet);

ipc.readable(() -> {
String data1 = ipc.read(StandardCharsets.UTF_8);

if (data1 == null) return;

ipc.readable(null);

Log.v("BareKit", data1);

ipc.writable(() -> {
boolean sent = ipc.write("Hello back!", StandardCharsets.UTF_8);

if (sent) {
ipc.writable(null);

String data2 = ipc.read(StandardCharsets.UTF_8);

if (data2 != null) {
Log.v("BareKit", data2);

looper.quit();
} else {
ipc.readable(() -> {
String data3 = ipc.read(StandardCharsets.UTF_8);

if (data3 == null) return;

ipc.readable(null);

Log.v("BareKit", data3);

looper.quit();
});
}
}
});
});

Looper.loop();

ipc.close();
}
}
Loading

0 comments on commit e18838a

Please sign in to comment.