mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-18 08:58:39 +00:00
99 lines
2.7 KiB
Nim
99 lines
2.7 KiB
Nim
import
|
|
streams, md5, sockets, unsigned,
|
|
sg_packets, zlib_helpers, idgen
|
|
type
|
|
TClientType* = enum
|
|
CServer = 0'i8, CPlayer, CUnknown
|
|
PClient* = ref TClient
|
|
TClient* = object of TObject
|
|
id*: int32
|
|
addy*: TupAddress
|
|
clientID*: uint16
|
|
auth*: bool
|
|
outputBuf*: PStringStream
|
|
case kind*: TClientType
|
|
of CPlayer:
|
|
alias*: string
|
|
session*: string
|
|
lastPing*: float
|
|
failedPings*: int
|
|
of CServer:
|
|
record*: ScZoneRecord
|
|
cfg*: TChecksumFile
|
|
of CUnknown: nil
|
|
TChecksumFile* = object
|
|
unpackedSize*: int
|
|
sum*: MD5Digest
|
|
compressed*: string
|
|
TupAddress* = tuple[host: string, port: int16]
|
|
PIDGen*[T: Ordinal] = ref TIDGen[T]
|
|
TIDGen[T: Ordinal] = object
|
|
max: T
|
|
freeIDs: seq[T]
|
|
var cliID = newIdGen[int32]()
|
|
|
|
proc sendMessage*(client: PClient; txt: string)
|
|
proc sendError*(client: PClient; txt: string)
|
|
proc `$`*(client: PClient): string
|
|
|
|
proc newIncomingBuffer*(size = 1024): PStringStream =
|
|
result = newStringStream("")
|
|
result.data.setLen size
|
|
result.data.setLen 0
|
|
result.flushImpl = proc(stream: PStream) =
|
|
stream.setPosition(0)
|
|
PStringStream(stream).data.setLen(0)
|
|
|
|
|
|
proc free*(c: PClient) =
|
|
echo "Client freed: ", c
|
|
cliID.del c.id
|
|
c.outputBuf.flush()
|
|
c.outputBuf = nil
|
|
proc newClient*(addy: TupAddress): PClient =
|
|
new(result, free)
|
|
result.addy = addy
|
|
result.outputBuf = newStringStream("")
|
|
result.outputBuf.flushImpl = proc(stream: PStream) =
|
|
stream.setPosition 0
|
|
PStringStream(stream).data.setLen 0
|
|
|
|
proc loginPlayer*(client: PClient; login: CsLogin): bool =
|
|
if client.auth:
|
|
client.sendError("You are already logged in.")
|
|
return
|
|
client.id = cliID.next()
|
|
client.auth = true
|
|
client.kind = CPlayer
|
|
client.alias = login.alias
|
|
client.session = getMD5(client.alias & $rand(10000))
|
|
result = true
|
|
|
|
proc `$`*(client: PClient): string =
|
|
if not client.auth: return $client.addy
|
|
case client.kind
|
|
of CPlayer: result = client.alias
|
|
of CServer: result = client.record.name
|
|
else: result = $client.addy
|
|
proc send*[T](client: PClient; pktType: char; pkt: var T) =
|
|
client.outputBuf.write(pktType)
|
|
pkt.pack(client.outputBuf)
|
|
|
|
proc sendMessage*(client: PClient; txt: string) =
|
|
var m = newScChat(CSystem, text = txt)
|
|
client.send HChat, m
|
|
proc sendError*(client: PClient; txt: string) =
|
|
var m = newScChat(CError, text = txt)
|
|
client.send HChat, m
|
|
|
|
proc checksumFile*(filename: string): TChecksumFile =
|
|
let fullText = readFile(filename)
|
|
result.unpackedSize = fullText.len
|
|
result.sum = toMD5(fullText)
|
|
result.compressed = compress(fullText)
|
|
proc checksumStr*(str: string): TChecksumFile =
|
|
result.unpackedSize = str.len
|
|
result.sum = toMD5(str)
|
|
result.compressed = compress(str)
|
|
|