/
Callout.swift
30 lines (28 loc) · 999 Bytes
/
Callout.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import Dispatch
import Foundation
import NoiseSerde
public func installCallback(
id: UInt64,
rpc: (UVarint, Varint) -> Future<String, Void>,
proc: @escaping (InputPort) -> Void
) -> Future<String, Void> {
callbacksSema.wait()
callbacks[id] = proc
callbacksSema.signal()
let addr = Int(bitPattern: unsafeBitCast(callbackHandler, to: Optional<UnsafeRawPointer>.self)!)
return rpc(id, Int64(addr))
}
fileprivate var callbacks = [UInt64: (InputPort) -> Void]()
fileprivate var callbacksSema = DispatchSemaphore(value: 1)
fileprivate let callbackHandler: @convention(c) (UInt64, Int, UnsafePointer<CChar>) -> Void = { id, len, ptr in
let data = Data(bytes: ptr, count: len)
let pipe = Pipe()
DispatchQueue.global(qos: .background).async {
try! pipe.fileHandleForWriting.write(contentsOf: data)
try! pipe.fileHandleForWriting.close()
}
callbacksSema.wait()
let proc = callbacks[id]
callbacksSema.signal()
proc!(InputPort(withHandle: pipe.fileHandleForReading))
}