import
tables, sg_packets, enet, estreams, sg_gui, sfml,
zlib_helpers, md5, sg_assets, os
type
PServer* = ptr TServer
TServer* = object
connected*: bool
addy: enet.TAddress
host*: PHost
peer*: PPeer
handlers*: Table[char, TScPktHandler]
TScPktHandler* = proc(serv: PServer; buffer: PBuffer)
TFileTransfer = object
fileName: string
assetType: TAssetType
fullLen: int
pos: int32
data: string
readyToSave: bool
var
currentFileTransfer: TFileTransfer
downloadProgress* = newButton(nil, "", vec2f(0,0), nil)
currentFileTransfer.data = ""
proc addHandler*(serv: PServer; packetType: char; handler: TScPktHandler) =
serv.handlers[packetType] = handler
proc newServer*(): PServer =
result = cast[PServer](alloc0(sizeof(TServer)))
result.connected = false
result.host = createHost(nil, 1, 2, 0, 0)
result.handlers = initTable[char, TScPktHandler](32)
proc connect*(serv: PServer; host: string; port: int16; error: var string): bool =
if setHost(serv.addy, host) != 0:
error = "Could not resolve host "
error.add host
return false
serv.addy.port = port.cushort
serv.peer = serv.host.connect(serv.addy, 2, 0)
if serv.peer.isNil:
error = "Could not connect to host "
error.add host
return false
return true
proc send*[T](serv: PServer; packetType: char; pkt: var T) =
if serv.connected:
var b = newBuffer(100)
b.write packetType
b.pack pkt
serv.peer.send(0.cuchar, b, FlagUnsequenced)
proc sendPubChat*(server: PServer; msg: string) =
var chat = newCsChat("", msg)
server.send HChat, chat
proc handlePackets*(server: PServer; buf: PBuffer) =
while not buf.atEnd():
let typ = readChar(buf)
if server.handlers.hasKey(typ):
server.handlers[typ](server, buf)
else:
break
proc updateFileProgress*() =
let progress = currentFileTransfer.pos / currentFileTransfer.fullLen
downloadProgress.bg.setSize(vec2f(progress * 100, 20))
downloadProgress.setString($currentFileTransfer.pos & '/' & $currentFileTransfer.fullLen)
## HFileTransfer
proc handleFilePartRecv*(serv: PServer; buffer: PBuffer) {.procvar.} =
var
f = readScFileTransfer(buffer)
updateFileProgress()
if not(f.pos == currentFileTransfer.pos):
echo "returning early from filepartrecv"
return ##issues, probably
if currentFileTransfer.data.len == 0:
echo "setting current file size"
currentFileTransfer.data.setLen f.fileSize
let len = f.data.len
copymem(
addr currentFileTransfer.data[f.pos],
addr f.data[0],
len)
currentFileTransfer.pos = f.pos + len.int32
if currentFileTransfer.pos == f.fileSize: #file should be done, rizzight
currentFileTransfer.data = uncompress(
currentFileTransfer.data, currentFileTransfer.fullLen)
currentFileTransfer.readyToSave = true
var resp: CsFileChallenge
resp.checksum = toMD5(currentFileTransfer.data)
serv.send HFileChallenge, resp
echo "responded with challenge (ready to save)"
else:
var resp = newCsFilepartAck(currentFileTransfer.pos)
serv.send HFileTransfer, resp
echo "responded for next part"
proc saveCurrentFile() =
if not currentFileTransfer.readyToSave: return
let
path = expandPath(currentFileTransfer.assetType, currentFileTransfer.fileName)
parent = parentDir(path)
if not existsDir(parent):
createDir(parent)
echo("Created dir")
writeFile path, currentFIleTransfer.data
echo "Write file"
## HChallengeResult
proc handleFileChallengeResult*(serv: PServer; buffer: PBuffer) {.procvar.} =
var res = readScChallengeResult(buffer).status
echo "got challnege result: ", res
if res and currentFileTransfer.readyToSave:
echo "saving"
saveCurrentFile()
else:
currentFileTransfer.readyToSave = false
currentFileTransfer.pos = 0
echo "REsetting current file"
## HFileCHallenge
proc handleFileChallenge*(serv: PServer; buffer: PBuffer) {.procvar.} =
var
challenge = readScFileChallenge(buffer)
path = expandPath(challenge)
resp: CsFileChallenge
if not existsFile(path):
resp.needFile = true
echo "Got file challenge, need file."
else:
resp.checksum = toMD5(readFile(path))
echo "got file challenge, sending sum"
currentFileTransfer.fileName = challenge.file
currentFileTransfer.assetType = challenge.assetType
currentFileTransfer.fullLen = challenge.fullLen.int
currentFileTransfer.pos = 0
currentFileTransfer.data.setLen 0
currentFileTransfer.readyToSave = false
serv.send HFileChallenge, resp