Source/Clients/XyoTcpipClient.swift
//
// XyoTcpipClient.swift
// sdk
//
// Created by Arie Trouw on 10/11/19.
// Copyright © 2019 Arie Trouw. All rights reserved.
//
import Foundation
import sdk_core_swift
struct TcpipClientError : Error {
enum ErrorKind {
case noBridges
}
let kind : ErrorKind
}
class XyoTcpipClient: XyoClient {
var stringHeuristic: String?
var enabledHeuristics: [XyoHeuristicEnum : XyoHeuristicGetter] = [:]
var knownBridges: [String] = []
var relayNode: XyoRelayNode
var procedureCatalog: XyoProcedureCatalog
weak var delegate: BoundWitnessDelegate?
public var pollingInterval : Int = 10// Not used in this client
var acceptBridging: Bool = false
var autoBridge: Bool = false {
didSet {
if (autoBridge) {
relayNode.addListener(key: "auto-bridging", listener: self)
} else {
relayNode.removeListener(key: "auto-bridging")
}
}
}
var autoBoundWitness: Bool = false
var scan: Bool = false
var semaphore = true
var ignoreLastBridgeBW : String? = nil
required init(relayNode: XyoRelayNode, procedureCatalog: XyoProcedureCatalog) {
self.procedureCatalog = procedureCatalog
self.relayNode = relayNode
self.enableHeursitics(heuristics: [.time, .string], enabled: true)
}
convenience init(relayNode: XyoRelayNode, procedureCatalog: XyoProcedureCatalog, autoBridge: Bool, acceptBridging: Bool, autoBoundWitness: Bool) {
self.init(relayNode: relayNode, procedureCatalog: procedureCatalog)
self.autoBridge = autoBridge
self.acceptBridging = acceptBridging
self.autoBoundWitness = autoBoundWitness
}
func startBridging() {
guard autoBridge == true && semaphore == true else {return}
print("Bound witness discovered, starting bridging")
do {
try bridge()
} catch {
print("Cant start bridging \(error)")
}
}
func bridge() throws {
guard semaphore == true, knownBridges.count > 0 else {
if knownBridges.count == 0 {
print("No known bridges")
}
return
}
semaphore = false
knownBridges.forEach { (bridge) in
let url = URL(string: bridge)!
let tcpDevice = XyoTcpPeer(ip: url.host!, port: UInt32(url.port!))
delegate?.boundWitness(started: url.host!)
let socket = XyoTcpSocket.create(peer: tcpDevice)
let pipe = XyoTcpSocketPipe(socket: socket, initiationData: nil)
let handler = XyoNetworkHandler(pipe: pipe)
relayNode.boundWitness(handler: handler, procedureCatalogue: procedureCatalog) { [weak self] (boundWitness, err) in
guard let strong = self else {return}
if (err != nil) {
DispatchQueue.main.async {
strong.delegate?.boundWitness(failed: tcpDevice.ip, withError: err!)
}
strong.semaphore = true
return
}
strong.ignoreLastBridgeBW = try? boundWitness?.getHash(hasher: strong.relayNode.hasher).getBuffer().toByteArray().toHexString() ?? ""
pipe.close()
if let bw = boundWitness, let strong = self {
DispatchQueue.main.async {
strong.delegate?.boundWitness(completed: tcpDevice.ip, withBoundWitness: bw)
}
}
strong.semaphore = true
}
}
}
deinit {
print("Deallocing Tcpip Network")
relayNode.removeListener(key: "auto-bridging")
}
}
extension XyoTcpipClient : XyoNodeListener {
func onBoundWitnessStart() {
}
func onBoundWitnessEndFailure() {
}
func onBoundWitnessEndSuccess(boundWitness: XyoBoundWitness) {
DispatchQueue.main.async { [weak self] in
guard let strong = self else { return }
let bwHash = try? boundWitness.getHash(hasher: strong.relayNode.hasher).getBuffer().toByteArray().toHexString()
if (bwHash != strong.ignoreLastBridgeBW) {
self?.startBridging()
}
}
}
func onBoundWitnessDiscovered(boundWitness: XyoBoundWitness) {
}
}