Started work on websocket communication: Parsing/Serialization of WebSocket packets.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import prompt, terminal, argparse, parsetoml
|
||||
import prompt, terminal, argparse, parsetoml, times
|
||||
import strutils, strformat, system, tables
|
||||
|
||||
import ./[agent, listener, builder]
|
||||
@@ -6,6 +6,8 @@ import ../globals
|
||||
import ../db/database
|
||||
import ../core/logger
|
||||
import ../../common/[types, crypto, profile]
|
||||
import ../protocol/websocket
|
||||
import mummy, mummy/routers
|
||||
|
||||
#[
|
||||
Argument parsing
|
||||
@@ -137,6 +139,33 @@ proc init*(T: type Conquest, profile: Profile): Conquest =
|
||||
cq.dbPath = CONQUEST_ROOT & "/" & profile.getString("database-file")
|
||||
return cq
|
||||
|
||||
#[
|
||||
WebSocket
|
||||
]#
|
||||
proc upgradeHandler(request: Request) =
|
||||
let ws = request.upgradeToWebSocket()
|
||||
|
||||
# Send client connection message
|
||||
ws.sendEventlogItem(LOG_SUCCESS_SHORT, now().toTime().toUnix(), "CQ-V1")
|
||||
|
||||
|
||||
proc websocketHandler(ws: WebSocket, event: WebSocketEvent, message: Message) =
|
||||
case event:
|
||||
of OpenEvent:
|
||||
discard
|
||||
of MessageEvent:
|
||||
ws.sendHeartbeat()
|
||||
of ErrorEvent:
|
||||
discard
|
||||
of CloseEvent:
|
||||
discard
|
||||
|
||||
proc serve(server: Server) {.thread.} =
|
||||
try:
|
||||
server.serve(Port(12345))
|
||||
except Exception:
|
||||
discard
|
||||
|
||||
proc startServer*(profilePath: string) =
|
||||
|
||||
# Ensure that the conquest root directory was passed as a compile-time define
|
||||
@@ -167,6 +196,13 @@ proc startServer*(profilePath: string) =
|
||||
cq.restartListeners()
|
||||
cq.addMultiple(cq.dbGetAllAgents())
|
||||
|
||||
var router: Router
|
||||
router.get("/*", upgradeHandler)
|
||||
let server = newServer(router, websocketHandler)
|
||||
|
||||
var thread: Thread[Server]
|
||||
createThread(thread, serve, server)
|
||||
|
||||
# Main loop
|
||||
while true:
|
||||
cq.prompt.setIndicator("[conquest]> ")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Compiler flags
|
||||
-d:server
|
||||
--threads:on
|
||||
--mm:orc
|
||||
-d:httpxServerName=""
|
||||
-o:"bin/server"
|
||||
47
src/server/protocol/websocket.nim
Normal file
47
src/server/protocol/websocket.nim
Normal file
@@ -0,0 +1,47 @@
|
||||
import times, tables
|
||||
import ../../common/[types, utils, serialize]
|
||||
import mummy
|
||||
|
||||
#[
|
||||
[ Sending functions ]
|
||||
Server -> Client
|
||||
]#
|
||||
proc sendHeartbeat*(ws: WebSocket) =
|
||||
var packer = Packer.init()
|
||||
|
||||
packer.add(cast[uint8](CLIENT_HEARTBEAT))
|
||||
let data = packer.pack()
|
||||
|
||||
ws.send(Bytes.toString(data), BinaryMessage)
|
||||
|
||||
proc sendEventlogItem*(ws: WebSocket, logType: LogType, timestamp: int64, message: string) =
|
||||
var packer = Packer.init()
|
||||
|
||||
packer.add(cast[uint8](CLIENT_EVENT_LOG))
|
||||
packer.add(cast[uint8](logType))
|
||||
packer.add(cast[uint32](timestamp))
|
||||
packer.addDataWithLengthPrefix(string.toBytes(message))
|
||||
let data = packer.pack()
|
||||
|
||||
ws.send(Bytes.toString(data), BinaryMessage)
|
||||
|
||||
#[
|
||||
[ Retrieval functions ]
|
||||
Client -> Server
|
||||
]#
|
||||
proc getMessageType*(message: Message): WsMessageAction =
|
||||
var unpacker = Unpacker.init(message.data)
|
||||
return cast[WsMessageAction](unpacker.getUint8())
|
||||
|
||||
proc receiveStartListener*(message: Message): Listener =
|
||||
var unpacker = Unpacker.init(message.data)
|
||||
|
||||
discard unpacker.getUint8()
|
||||
|
||||
return Listener(
|
||||
server: nil,
|
||||
listenerId: Uuid.toString(unpacker.getUint32()),
|
||||
address: unpacker.getDataWithLengthPrefix(),
|
||||
port: int(unpacker.getUint16()),
|
||||
protocol: cast[Protocol](unpacker.getUint8())
|
||||
)
|
||||
Reference in New Issue
Block a user