client_helpers.nim 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import
  2. tables, sg_packets, enet, estreams, sg_gui, sfml,
  3. zlib_helpers, md5, sg_assets, os
  4. type
  5. PServer* = ptr TServer
  6. TServer* = object
  7. connected*: bool
  8. addy: enet.TAddress
  9. host*: PHost
  10. peer*: PPeer
  11. handlers*: Table[char, TScPktHandler]
  12. TScPktHandler* = proc(serv: PServer; buffer: PBuffer)
  13. TFileTransfer = object
  14. fileName: string
  15. assetType: TAssetType
  16. fullLen: int
  17. pos: int32
  18. data: string
  19. readyToSave: bool
  20. var
  21. currentFileTransfer: TFileTransfer
  22. downloadProgress* = newButton(nil, "", vec2f(0,0), nil)
  23. currentFileTransfer.data = ""
  24. proc addHandler*(serv: PServer; packetType: char; handler: TScPktHandler) =
  25. serv.handlers[packetType] = handler
  26. proc newServer*(): PServer =
  27. result = cast[PServer](alloc0(sizeof(TServer)))
  28. result.connected = false
  29. result.host = createHost(nil, 1, 2, 0, 0)
  30. result.handlers = initTable[char, TScPktHandler](32)
  31. proc connect*(serv: PServer; host: string; port: int16; error: var string): bool =
  32. if setHost(serv.addy, host) != 0:
  33. error = "Could not resolve host "
  34. error.add host
  35. return false
  36. serv.addy.port = port.cushort
  37. serv.peer = serv.host.connect(serv.addy, 2, 0)
  38. if serv.peer.isNil:
  39. error = "Could not connect to host "
  40. error.add host
  41. return false
  42. return true
  43. proc send*[T](serv: PServer; packetType: char; pkt: var T) =
  44. if serv.connected:
  45. var b = newBuffer(100)
  46. b.write packetType
  47. b.pack pkt
  48. serv.peer.send(0.cuchar, b, FlagUnsequenced)
  49. proc sendPubChat*(server: PServer; msg: string) =
  50. var chat = newCsChat("", msg)
  51. server.send HChat, chat
  52. proc handlePackets*(server: PServer; buf: PBuffer) =
  53. while not buf.atEnd():
  54. let typ = readChar(buf)
  55. if server.handlers.hasKey(typ):
  56. server.handlers[typ](server, buf)
  57. else:
  58. break
  59. proc updateFileProgress*() =
  60. let progress = currentFileTransfer.pos / currentFileTransfer.fullLen
  61. downloadProgress.bg.setSize(vec2f(progress * 100, 20))
  62. downloadProgress.setString($currentFileTransfer.pos & '/' & $currentFileTransfer.fullLen)
  63. ## HFileTransfer
  64. proc handleFilePartRecv*(serv: PServer; buffer: PBuffer) =
  65. var
  66. f = readScFileTransfer(buffer)
  67. updateFileProgress()
  68. if not(f.pos == currentFileTransfer.pos):
  69. echo "returning early from filepartrecv"
  70. return ##issues, probably
  71. if currentFileTransfer.data.len == 0:
  72. echo "setting current file size"
  73. currentFileTransfer.data.setLen f.fileSize
  74. let len = f.data.len
  75. copymem(
  76. addr currentFileTransfer.data[f.pos],
  77. addr f.data[0],
  78. len)
  79. currentFileTransfer.pos = f.pos + len.int32
  80. if currentFileTransfer.pos == f.fileSize: #file should be done, rizzight
  81. currentFileTransfer.data = uncompress(
  82. currentFileTransfer.data, currentFileTransfer.fullLen)
  83. currentFileTransfer.readyToSave = true
  84. var resp: CsFileChallenge
  85. resp.checksum = toMD5(currentFileTransfer.data)
  86. serv.send HFileChallenge, resp
  87. echo "responded with challenge (ready to save)"
  88. else:
  89. var resp = newCsFilepartAck(currentFileTransfer.pos)
  90. serv.send HFileTransfer, resp
  91. echo "responded for next part"
  92. proc saveCurrentFile() =
  93. if not currentFileTransfer.readyToSave: return
  94. let
  95. path = expandPath(currentFileTransfer.assetType, currentFileTransfer.fileName)
  96. parent = parentDir(path)
  97. if not dirExists(parent):
  98. createDir(parent)
  99. echo("Created dir")
  100. writeFile path, currentFIleTransfer.data
  101. echo "Write file"
  102. ## HChallengeResult
  103. proc handleFileChallengeResult*(serv: PServer; buffer: PBuffer) =
  104. var res = readScChallengeResult(buffer).status
  105. echo "got challnege result: ", res
  106. if res and currentFileTransfer.readyToSave:
  107. echo "saving"
  108. saveCurrentFile()
  109. else:
  110. currentFileTransfer.readyToSave = false
  111. currentFileTransfer.pos = 0
  112. echo "REsetting current file"
  113. ## HFileCHallenge
  114. proc handleFileChallenge*(serv: PServer; buffer: PBuffer) =
  115. var
  116. challenge = readScFileChallenge(buffer)
  117. path = expandPath(challenge)
  118. resp: CsFileChallenge
  119. if not fileExists(path):
  120. resp.needFile = true
  121. echo "Got file challenge, need file."
  122. else:
  123. resp.checksum = toMD5(readFile(path))
  124. echo "got file challenge, sending sum"
  125. currentFileTransfer.fileName = challenge.file
  126. currentFileTransfer.assetType = challenge.assetType
  127. currentFileTransfer.fullLen = challenge.fullLen.int
  128. currentFileTransfer.pos = 0
  129. currentFileTransfer.data.setLen 0
  130. currentFileTransfer.readyToSave = false
  131. serv.send HFileChallenge, resp