all repos — wsabi @ a7da3efc1b09d7391af3df752d37f68850a7f299

websocket proxy that sends stats to statsd

src/wsabi.nim (view raw)

 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
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
import asyncnet, asyncdispatch
import wsabipkg/utils

type
  Server = ref object
    socket: AsyncSocket
    clients: seq[Client]

  Client = ref object
    socket: AsyncSocket
    netAddr: string
    id: int
    connected: bool

proc `$`(client: Client): string =
  $client.id & "(" & client.netAddr & ")"

proc newServer(): Server =
  Server(socket: newAsyncSocket(), clients: @[])

proc sendRemote(remote: AsyncSocket, line: string) {.async.} =
  await remote.send(line & "\c\L")
  let msg = await remote.recv(10000)
  if msg.len == 0:
    echo("remote closed connection")
    remote.close()
    quit 0
  else:
    echo msg

proc processMsgs(
  server: Server, client: Client, 
  remote: AsyncSocket
  ) {.async.} =
  while true:
    let line = await client.socket.recvLine()

    if line.len == 0:
      echo(client, " disconnected!")
      client.connected = false

      client.socket.close()
      return

    echo(client, "sent: ", line)
    asyncCheck sendRemote(remote, line)

proc loop(server: Server, port = 6000) {.async.} =
  server.socket.bindAddr(port.Port)
  echo("server initialised!")
  server.socket.listen()
  echo("listening on localhost:", port)
  let remote = newAsyncSocket()
  await remote.connect("example.com", 80.Port)
  echo("connecting to remote... ")
  echo("connected to remote:", getPeerAddr(remote))

  while true:
    let (netAddr, clientSocket) = await server.socket.acceptAddr()
    echo("accepted connection from ", netAddr)

    let client = Client(
      socket: clientSocket,
      netAddr: netAddr,
      id: server.clients.len,
      connected: true
    )
    server.clients.add(client)
    asyncCheck processMsgs(server, client, remote)
  
when isMainModule:
  setControlCHook(handleCtrlC)
  var server = newServer()
  try:
    waitFor loop(server)
  except EKeyboardInterrupt:
    echo("interrupted! closing sockets...")
    server.socket.close()
    quit 0