all repos — wsabi @ 40d0b91db3691306d76c06c22e94eab5a7ab6d20

websocket proxy that sends stats to statsd

Initial working prototype

The websocket stream opens!  Still need to figure out why subsequent
packets don't get sent.
Anirudh Oppiliappan x@icyphox.sh
Tue, 21 Jul 2020 17:52:00 +0530
commit

40d0b91db3691306d76c06c22e94eab5a7ab6d20

parent

c58143fd9c458ad4fbab1cca6b59f0863655afc5

4 files changed, 88 insertions(+), 20 deletions(-)

jump to
M src/config.nimssrc/config.nims

@@ -1,1 +1,1 @@

---d:ssl +--d: ssl
A src/utils/args.nim

@@ -0,0 +1,38 @@

+import parseopt, strutils +import os + +var + remoteHost*: seq[string] + localPort*: int + + +proc printHelp = + const msg = """ +wsabi - load balance, monitor and failover Openfire websockets + +usage: + wsabi --localPort=PORT --remoteHost=REMOTE,REMOTE... + """ + echo msg + +proc parseArgs* = + var p = initOptParser() + if paramCount() == 0: + printHelp() + quit 0 + while true: + p.next() + case p.kind + of cmdEnd: break + of cmdLongOption: + if p.key == "localPort": + localPort = parseInt(p.val) + elif p.key == "remoteHost": + remoteHost = p.val.strip().split(",") + else: + printHelp() + quit 0 + of cmdArgument, cmdShortOption: + printHelp() + quit 0 +
M src/wsabi.nimsrc/wsabi.nim

@@ -1,32 +1,63 @@

-import ws, asyncdispatch, asynchttpserver +import + ws, + asyncdispatch, + asynchttpserver, + strformat, + asyncnet, + utils/args, + strutils, + uri -# Global vars var server = newAsyncHttpServer() remote: WebSocket proc connectRemote(host: string) {.async.} = - remote = await newWebSocket(host) - echo "connected to remote" + remote = await newWebSocket(host, protocol = "xmpp") + let + hostPort = remote.tcpSocket.getPeerAddr() + address = hostPort[0] + port = hostPort[1].int + echo fmt"connected to {address}:{port}" -proc sendRemote(ws: WebSocket, data: string) {.async.} = +# Sends a message to, and returns a response from the remote +proc sendRemote(ws: WebSocket, data: string): Future[string] {.async.} = await ws.send(data) - echo await ws.receiveStrPacket() + result = await ws.receiveStrPacket() + +proc localServer(req: Request) {.async, gcsafe.} = + 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] + + var client = await newWebSocket(newreq, protocol = "xmpp") -proc localServer(req: Request) {.async.} = - var - ws = await newWebSocket(req) + try: + while client.readyState == Open: + # TODO: don't hardcode these replacements + var + packet = await client.receiveStrPacket() + repacket = packet.replace("127.0.0.1", by=bits.hostname) + echo "local msg: " & repacket - await connectRemote("ws://test.ws-benchmark.cometchat-dev.com:7070/ws/") - try: - while ws.readyState == Open: - let packet = await ws.receiveStrPacket() - echo "local msg: " & packet - await sendRemote(remote, packet) - except WebSocketError: - echo "client closed socket" + # TODO: don't hardcode these replacements + var + res = await sendRemote(remote, repacket) + reres = res.replace(bits.hostname, by="127.0.0.1") + echo "sending response: ", reres + await client.send(reres) + except WebSocketError: + echo "client closed socket: ", getCurrentExceptionMsg() when isMainModule: - waitFor server.serve(Port(9001), localServer) + parseArgs() + echo "connecting to remote host..." + waitFor connectRemote(remoteHost[0]) + echo fmt"local server listening on ws://127.0.0.1:{localPort}" + waitFor server.serve(Port(localPort), localServer)
M wsabi.nimblewsabi.nimble

@@ -8,7 +8,6 @@ srcDir = "src"

bin = @["wsabi"] - # Dependencies requires "nim >= 1.0"