import ws, asyncdispatch, asynchttpserver, strformat, asyncnet, wsabipkg/[args,httputils], httpclient, strutils, json, uri # var # server = newAsyncHttpServer() # remote: WebSocket # client: WebSocket # clients: newSeq[WebSocket]() type Client = object ws: WebSocket remote: WebSocket var server = newAsyncHttpServer() client: Client clients = newSeq[Client]() # proc connectRemote(remote: WebSocket, host: string) {.async.} = # remote = await newWebSocket(host, protocol = "xmpp") # let (address, port) = remote.tcpSocket.getPeerAddr() # echo fmt"connected to {address}:{port.int}" proc commRemoteClient(c: Client) {.async.} = ## Fetch from remote and send to client while c.remote.readyState == Open: echo "yes open" var data = await c.remote.receiveStrPacket() echo "from remote: ", data await c.ws.send(data proc localServer(req: Request) {.async, gcsafe.} = ## Listen on localhost:PORT/ws if req.url.path == "/ws": var newreq = req # TODO: loop through for all remote hosts let bits = parseUri(remoteHost[0]) newreq.headers["host"] = @[fmt"{bits.hostname}:{bits.port}"] newreq.headers["hostname"] = @[bits.hostname] client.ws = await newWebSocket(newreq, protocol = "xmpp") echo "connecting to remote host..." client.remote = await newWebSocket(remoteHost[0], protocol = "xmpp") let (address, port) = client.remote.tcpSocket.getPeerAddr() echo fmt"connected to {address}:{port.int}" clients.add client try: while client.ws.readyState == Open: # TODO: don't hardcode these replacements var packet = await client.ws.receiveStrPacket() repacket = packet.replace("127.0.0.1", by=bits.hostname) echo "from local: " & repacket await client.remote.send(repacket) echo "sent local packet" asyncCheck commRemoteClient(client) except WebSocketError: echo "client closed socket: ", getCurrentExceptionMsg() ## Health check endpoint ## The 'uri' can be either 'ws' or 'http'. if req.url.path == "/check-health": if req.reqMethod == HttpPost: type HealthCheck = object uri: string host: string port: int try: let hcJson = parseJson(req.body) hc = to(hcJson, HealthCheck) ## Check if host is a websocket, and try for the xmpp protocol if hc.uri in ["ws", "wss"]: let hostStr = &"{hc.uri}://{hc.host}:{hc.port}/ws/" echo &"connecting to {hostStr}" var ws = await newWebSocket(hostStr, protocol = "xmpp") echo "sending test packet" echo &"""""" await ws.send(&"""""") echo await ws.receiveStrPacket() ws.close() let r = %*{"status": "OK"} await req.makeResponse(Http200, $r) if hc.uri in ["http", "https"]: let hostStr = &"{hc.uri}://{hc.host}:{hc.port}/" echo &"connecting to {hostStr}" var tmpClient = newAsyncHttpClient() echo await tmpClient.getContent(hostStr) let r = %*{"status": "OK"} await req.makeResponse(Http200, $r) else: let r = %*{"status": "error", "msg": &"unknown URI {hc.uri}"} await req.makeResponse(Http400, $r) except OSError as e: echo "unable to reach specified host:port pair" let r = %*{ "status": "error", "msg": e.msg } await req.makeResponse(Http400, $r) except KeyError as e: let r = %*{"status": "error", "msg": e.msg} await req.makeResponse(Http400, $r) except WebSocketError as e: let r = %*{"status": "error", "msg": e.msg} await req.makeResponse(Http500, $r) when isMainModule: parseArgs() echo fmt"local server running at ws://127.0.0.1:{localPort}/ws" asyncCheck server.serve(Port(localPort), localServer) echo "calling commRemoteClient" runForever()