diff options
Diffstat (limited to 'iono/iono.swift')
-rw-r--r-- | iono/iono.swift | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/iono/iono.swift b/iono/iono.swift new file mode 100644 index 0000000..77a4ec5 --- /dev/null +++ b/iono/iono.swift @@ -0,0 +1,113 @@ +/* + * 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 <http://www.gnu.org/licenses/> + */ + +import Foundation + +protocol IonoMessageHandler { + func handleMessage(message: String) +} + +func notification_callback(payload: Optional<UnsafePointer<Int8>>, + userdata: Optional<UnsafeMutableRawPointer>) { + let native = Unmanaged<Iono>.fromOpaque(userdata!).takeUnretainedValue() + let string = String(cString: payload!) + native.internalOnNotify(payload: string) +} + +class Iono { + var instance: OpaquePointer! + var work_queue: DispatchQueue + var initialization_group: DispatchGroup + var messageHandler: IonoMessageHandler? + + init() { + 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 { + __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 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) { + 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 waitStopped() { + + } + + func putModuleCode(modName: String, code: String) { + scheduleNodeThreadSync { + __putModuleCodeNative(self.instance, modName.cString(using: .utf8), + code.cString(using: .utf8)) + } + } +} |