From 23dd40ea4c7d5340bdd18e9c3b2107a179e23850 Mon Sep 17 00:00:00 2001 From: Jonathan Buchanan Date: Mon, 7 Jun 2021 19:46:48 -0400 Subject: continue implementing node wrapper & tests --- Taler/NodeWrapper.swift | 106 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 22 deletions(-) (limited to 'Taler/NodeWrapper.swift') diff --git a/Taler/NodeWrapper.swift b/Taler/NodeWrapper.swift index 60ca92b..ec0ba58 100644 --- a/Taler/NodeWrapper.swift +++ b/Taler/NodeWrapper.swift @@ -1,49 +1,111 @@ -// -// NodeWrapper.swift -// Taler -// -// Created by Jonathan Buchanan on 1/14/21. -// Copyright © 2021 Taler. All rights reserved. -// +/* + * This file is part of GNU Taler + * (C) 2021 Taler Systems S.A. + * + * GNU Taler is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3, or (at your option) any later version. + * + * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * GNU Taler; see the file COPYING. If not, see + */ import Foundation +protocol IonoMessageHandler { + func handleMessage(message: String) +} + +func notification_callback(payload: Optional>, + userdata: Optional) { + let native = Unmanaged.fromOpaque(userdata!).takeUnretainedValue() + let string = String(cString: payload!) + native.internalOnNotify(payload: string) +} + class Iono { - var __instance: OpaquePointer - var messageHandler: ((String) -> ())? + var instance: OpaquePointer! + var work_queue: DispatchQueue + var initialization_group: DispatchGroup + var messageHandler: IonoMessageHandler? init() { - __instance = __new_instance() + work_queue = DispatchQueue(label: "NodeQueue", qos: .userInitiated) + initialization_group = DispatchGroup() + initialization_group.notify(queue: work_queue) { + self.instance = __initNative() + __setNotifyHandler(self.instance, notification_callback, Unmanaged.passUnretained(self).toOpaque()) + } } deinit { - __free_instance(__instance) + __destroyNative(instance) + } + + private func scheduleNodeThreadAsync(block: @escaping () -> Void) { + initialization_group.wait() + work_queue.async(execute: block) + notifyNative() + } + + private func scheduleNodeThreadSync(block: @escaping () -> Void) { + initialization_group.wait() + work_queue.sync(execute: block) + notifyNative() + } + + func internalOnNotify(payload: String) { + if let handler = messageHandler { + handler.handleMessage(message: payload) + } } func notifyNative() { - + initialization_group.wait() + __notifyNative(instance) } - func evalJS(source: String) -> String { - var result_cstr: UnsafeMutablePointer = __eval_js(source.cString(using: .utf8), __instance) - var result = String(cString: result_cstr) - free(result_cstr) - return result + func evalSimpleJs(source: String) -> String { + var result: String? + scheduleNodeThreadSync { + let cResult = __evalJs(self.instance, source.cString(using: .utf8)) + if let cStr = cResult { + result = String(cString: cStr) + free(cResult) + } + } + return result! } func evalNodeCode(source: String) { - __make_callback(source.cString(using: .utf8), __instance) + scheduleNodeThreadAsync { + __makeCallbackNative(self.instance, source.cString(using: .utf8)) + } } func sendMessage(message: String) { - + let encoded = message.data(using: .utf8)!.base64EncodedString() + let source = """ + if (global.__iono_onMessage) { + const msg = (new Buffer('\(encoded)', 'base64')).toString('ascii'); + global.__iono_onMessage(msg); + } else { + console.log("WARN: no __iono_onMessage defined"); + } + """ + evalNodeCode(source: source) } - func waitUntilStopped() { + func waitStopped() { } - func putModuleCode(moduleName: String, code: String) { - __put_module_code(moduleName.cString(using: .utf8), code.cString(using: .utf8), __instance) + func putModuleCode(modName: String, code: String) { + __putModuleCodeNative(instance, modName.cString(using: .utf8), + code.cString(using: .utf8)) } } -- cgit v1.2.3