120 lines
3.7 KiB
Nim
120 lines
3.7 KiB
Nim
import enet, sg_packets, estreams, md5, zlib_helpers, client_helpers, strutils,
|
|
idgen, sg_assets, tables, os
|
|
type
|
|
PClient* = ref object
|
|
id*: int32
|
|
auth*: bool
|
|
alias*: string
|
|
peer*: PPeer
|
|
|
|
FileChallengePair* = tuple[challenge: ScFileChallenge; file: TChecksumFile]
|
|
PFileChallengeSequence* = ref TFileChallengeSequence
|
|
TFileChallengeSequence = object
|
|
index: int #which file is active
|
|
transfer: ScFileTransfer
|
|
file: ptr FileChallengePair
|
|
var
|
|
clientID = newIdGen[int32]()
|
|
myAssets*: seq[FileChallengePair] = @[]
|
|
fileChallenges = initTable[int32, PFileChallengeSequence](32)
|
|
const FileChunkSize = 256
|
|
|
|
proc free(client: PClient) =
|
|
if client.id != 0:
|
|
fileChallenges.del client.id
|
|
clientID.del client.id
|
|
proc newClient*(): PClient =
|
|
new(result, free)
|
|
result.id = clientID.next()
|
|
result.alias = "billy"
|
|
|
|
proc `$`*(client: PClient): string =
|
|
result = "$1:$2".format(client.id, client.alias)
|
|
|
|
proc send*[T](client: PClient; pktType: char; pkt: var T) =
|
|
var buf = newBuffer(128)
|
|
buf.write pktType
|
|
buf.pack pkt
|
|
discard client.peer.send(0.cuchar, buf, flagReliable)
|
|
|
|
proc sendMessage*(client: PClient; txt: string) =
|
|
var m = newScChat(CSystem, text = txt)
|
|
client.send HChat, m
|
|
proc sendError*(client: PClient; error: string) =
|
|
var m = newScChat(CError, text = error)
|
|
client.send HChat, m
|
|
|
|
|
|
|
|
|
|
proc next*(challenge: PFileChallengeSequence, client: PClient)
|
|
proc sendChunk*(challenge: PFileChallengeSequence, client: PClient)
|
|
|
|
proc startVerifyingFiles*(client: PClient) =
|
|
var fcs: PFileChallengeSequence
|
|
new(fcs)
|
|
fcs.index = -1
|
|
fileChallenges[client.id] = fcs
|
|
next(fcs, client)
|
|
|
|
proc next*(challenge: PFileChallengeSequence, client: PClient) =
|
|
inc(challenge.index)
|
|
if challenge.index >= myAssets.len:
|
|
client.sendMessage "You are cleared to enter"
|
|
fileChallenges.del client.id
|
|
return
|
|
else:
|
|
echo myAssets.len, "assets"
|
|
challenge.file = addr myAssets[challenge.index]
|
|
client.send HFileChallenge, challenge.file.challenge # :rolleyes:
|
|
echo "sent challenge"
|
|
|
|
proc sendChunk*(challenge: PFileChallengeSequence, client: PClient) =
|
|
let size = min(FileChunkSize, challenge.transfer.fileSize - challenge.transfer.pos)
|
|
challenge.transfer.data.setLen size
|
|
copyMem(
|
|
addr challenge.transfer.data[0],
|
|
addr challenge.file.file.compressed[challenge.transfer.pos],
|
|
size)
|
|
client.send HFileTransfer, challenge.transfer
|
|
echo "chunk sent"
|
|
|
|
proc startSend*(challenge: PFileChallengeSequence, client: PClient) =
|
|
challenge.transfer.fileSize = challenge.file.file.compressed.len().int32
|
|
challenge.transfer.pos = 0
|
|
challenge.transfer.data = ""
|
|
challenge.transfer.data.setLen FileChunkSize
|
|
challenge.sendChunk(client)
|
|
echo "starting xfer"
|
|
|
|
## HFileTransfer
|
|
proc handleFilePartAck*(client: PClient; buffer: PBuffer) =
|
|
echo "got filepartack"
|
|
var
|
|
ftrans = readCsFilepartAck(buffer)
|
|
fcSeq = fileChallenges[client.id]
|
|
fcSeq.transfer.pos = ftrans.lastPos
|
|
fcSeq.sendChunk client
|
|
|
|
## HFileCHallenge
|
|
proc handleFileChallengeResp*(client: PClient; buffer: PBuffer) =
|
|
echo "got file challenge resp"
|
|
var
|
|
fcResp = readCsFileChallenge(buffer)
|
|
fcSeq = fileChallenges[client.id]
|
|
let index = $(fcSeq.index + 1) / $(myAssets.len)
|
|
if fcResp.needFile:
|
|
client.sendMessage "Sending file... "&index
|
|
fcSeq.startSend(client)
|
|
else:
|
|
var resp = newScChallengeResult(false)
|
|
if fcResp.checksum == fcSeq.file.file.sum: ##client is good
|
|
client.sendMessage "Checksum is good. "&index
|
|
resp.status = true
|
|
client.send HChallengeResult, resp
|
|
fcSeq.next(client)
|
|
else:
|
|
client.sendMessage "Checksum is bad, sending file... "&index
|
|
client.send HChallengeResult, resp
|
|
fcSeq.startSend(client)
|
|
|