2021-06-27 06:35:36 +00:00
|
|
|
## nim-websock
|
2021-06-20 04:27:50 +00:00
|
|
|
## Copyright (c) 2021 Status Research & Development GmbH
|
|
|
|
## Licensed under either of
|
|
|
|
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
|
|
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
|
|
## at your option.
|
|
|
|
## This file may not be copied, modified, or distributed except according to
|
|
|
|
## those terms.
|
|
|
|
|
2021-06-14 23:20:28 +00:00
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
2021-06-11 20:04:09 +00:00
|
|
|
import std/[strutils, random]
|
|
|
|
import pkg/[
|
|
|
|
chronos,
|
|
|
|
chronos/streams/tlsstream,
|
|
|
|
httputils,
|
|
|
|
chronicles,
|
|
|
|
stew/byteutils]
|
|
|
|
|
2021-06-27 06:35:36 +00:00
|
|
|
import ../websock/websock
|
2021-06-11 20:04:09 +00:00
|
|
|
import ./keys
|
|
|
|
|
|
|
|
let
|
|
|
|
WSSecureKey* = TLSPrivateKey.init(SecureKey)
|
|
|
|
WSSecureCert* = TLSCertificate.init(SecureCert)
|
|
|
|
|
|
|
|
const WSPath* = when defined secure: "/wss" else: "/ws"
|
|
|
|
|
|
|
|
proc rndStr*(size: int): string =
|
|
|
|
for _ in 0..<size:
|
|
|
|
add(result, char(rand(int('A') .. int('z'))))
|
|
|
|
|
|
|
|
proc rndBin*(size: int): seq[byte] =
|
|
|
|
for _ in 0..<size:
|
|
|
|
add(result, byte(rand(0 .. 255)))
|
|
|
|
|
|
|
|
proc waitForClose*(ws: WSSession) {.async.} =
|
|
|
|
try:
|
|
|
|
while ws.readystate != ReadyState.Closed:
|
|
|
|
discard await ws.recv()
|
|
|
|
except CatchableError:
|
|
|
|
trace "Closing websocket"
|
|
|
|
|
|
|
|
proc createServer*(
|
|
|
|
address = initTAddress("127.0.0.1:8888"),
|
|
|
|
tlsPrivateKey = WSSecureKey,
|
|
|
|
tlsCertificate = WSSecureCert,
|
|
|
|
handler: HttpAsyncCallback = nil,
|
|
|
|
flags: set[ServerFlags] = {ServerFlags.TcpNoDelay, ServerFlags.ReuseAddr},
|
|
|
|
tlsFlags: set[TLSFlags] = {},
|
|
|
|
tlsMinVersion = TLSVersion.TLS12,
|
2021-06-14 23:20:28 +00:00
|
|
|
tlsMaxVersion = TLSVersion.TLS12): HttpServer
|
|
|
|
{.raises: [Defect, HttpError].} =
|
|
|
|
try:
|
|
|
|
let server = when defined secure:
|
|
|
|
TlsHttpServer.create(
|
|
|
|
address = address,
|
|
|
|
tlsPrivateKey = tlsPrivateKey,
|
|
|
|
tlsCertificate = tlsCertificate,
|
|
|
|
flags = flags,
|
|
|
|
tlsFlags = tlsFlags,
|
|
|
|
tlsMinVersion = tlsMinVersion,
|
|
|
|
tlsMaxVersion = tlsMaxVersion)
|
|
|
|
else:
|
|
|
|
HttpServer.create(
|
|
|
|
address = address,
|
|
|
|
flags = flags)
|
|
|
|
|
|
|
|
when defined accepts:
|
|
|
|
proc accepts() {.async, raises: [Defect].} =
|
|
|
|
try:
|
|
|
|
let req = await server.accept()
|
|
|
|
await req.handler()
|
|
|
|
except TransportOsError as exc:
|
|
|
|
error "Transport error", exc = exc.msg
|
|
|
|
|
|
|
|
asyncCheck accepts()
|
|
|
|
else:
|
|
|
|
server.handler = handler
|
|
|
|
server.start()
|
|
|
|
|
|
|
|
return server
|
|
|
|
except CatchableError as exc:
|
|
|
|
raise newException(Defect, exc.msg)
|
2021-06-11 20:04:09 +00:00
|
|
|
|
|
|
|
proc connectClient*(
|
|
|
|
address = initTAddress("127.0.0.1:8888"),
|
|
|
|
path = WSPath,
|
|
|
|
protocols: seq[string] = @["proto"],
|
|
|
|
flags: set[TLSFlags] = {TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName},
|
|
|
|
version = WSDefaultVersion,
|
|
|
|
frameSize = WSDefaultFrameSize,
|
|
|
|
onPing: ControlCb = nil,
|
|
|
|
onPong: ControlCb = nil,
|
|
|
|
onClose: CloseCb = nil,
|
|
|
|
rng: Rng = nil): Future[WSSession] {.async.} =
|
|
|
|
let secure = when defined secure: true else: false
|
|
|
|
return await WebSocket.connect(
|
2021-07-15 00:51:39 +00:00
|
|
|
host = address,
|
2021-06-11 20:04:09 +00:00
|
|
|
flags = flags,
|
|
|
|
path = path,
|
|
|
|
secure = secure,
|
|
|
|
protocols = protocols,
|
|
|
|
version = version,
|
|
|
|
frameSize = frameSize,
|
|
|
|
onPing = onPing,
|
|
|
|
onPong = onPong,
|
|
|
|
onClose = onClose,
|
|
|
|
rng = rng)
|