From 1071e63d1c49d75e6b2cbe01f80b89e84e5db71f Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Wed, 5 Jun 2019 21:57:13 +0200 Subject: [PATCH] File transfers --- src/blobset.nim | 84 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/src/blobset.nim b/src/blobset.nim index 1c832a7..64109a2 100644 --- a/src/blobset.nim +++ b/src/blobset.nim @@ -52,31 +52,79 @@ when defined(spry): discard result.evalRoot("""[loadFile: "blobs.sy"]""") when defined(tox) and defined(spry): + type IngestTransfer = object + name: string + stream: IngestStream + size, pos: uint64 + + proc process( + t: var IngestTransfer; tox: Tox; friend: Friend; file: FileTransfer; + pos: uint64; data: pointer; size: int): bool = + ## Process transfer data, return true if transfer is complete + if t.pos != pos: + cancel t.stream + tox.control(friend, file, TOX_FILE_CONTROL_CANCEL) + discard tox.send(friend, """stream is at position $# but you sent $#""" % [$t.pos, $pos]) + result = true + else: + waitFor t.stream.ingest(data, size) + t.pos.inc size + if t.pos >= t.size: + let blobId, blobSize = waitFor t.stream.finish() + discard tox.send(friend, """$# $# $#""" % [t.name, $blobId, $blobSize]) + result = true + + type Transfer = uint64 + proc `+`(friend: Friend; file: FileTransfer): Transfer = + (friend.Transfer shl 32) or file.Transfer + proc setupCallbacks(tox: Tox) = tox.onSelfConnectionStatus do (status: TOX_CONNECTION): echo "self status is ", status - let - store = openStore() - spry = newSpry(store) - proc eval(code: string): string {.gcsafe.} = - $(spry.evalRoot(code)) - tox.onFriendMessage do (friend: Friend; msg: string; kind: TOX_MESSAGE_TYPE): - try: - if kind == TOX_MESSAGE_TYPE_NORMAL: - tox.typing(friend, true) - let res = eval("[" & msg & "]") - tox.typing(friend, false) - discard tox.send(friend, $res, TOX_MESSAGE_TYPE_ACTION) - except: - discard tox.send(friend, getCurrentExceptionMsg()) - tox.onFriendRequest do (key: PublicKey; msg: string): echo "friend request from ", key, ", ", msg discard tox.addFriendNoRequest(key) + block: + let + store = openStore() + spry = newSpry(store) + transfers = newTable[Transfer, IngestTransfer](16) + tox.onFriendMessage do (friend: Friend; msg: string; kind: TOX_MESSAGE_TYPE): + try: + if kind == TOX_MESSAGE_TYPE_NORMAL: + tox.typing(friend, true) + let res = spry.evalRoot("[" & msg & "]") + tox.typing(friend, false) + discard tox.send(friend, $res, TOX_MESSAGE_TYPE_ACTION) + except: + discard tox.send(friend, getCurrentExceptionMsg()) + tox.onFileRecv do (friend: Friend; file: FileTransfer; kind: uint32; size: uint64; filename: string): + case kind + of (uint32)TOX_FILE_KIND_AVATAR: + tox.control(friend, file, TOX_FILE_CONTROL_CANCEL) + else: + if transfers.len > 16: + tox.control(friend, file, TOX_FILE_CONTROL_CANCEL) + discard tox.send(friend, "too many transfers are pending") + else: + let msg = """you are trying to send me "$#", type $#, size $#""" % + [filename, $kind, $size] + discard tox.send(friend, msg) + transfers[friend+file] = IngestTransfer( + name: filename, + stream: store.openIngestStream(size.BiggestInt), + size: size) + tox.control(friend, file, TOX_FILE_CONTROL_RESUME) + tox.onFileRecvChunk do (friend: Friend; file: FileTransfer; pos: uint64; data: pointer; size: int): + try: + if transfers[friend+file].process(tox, friend, file, pos, data, size): + transfers.del(friend+file) + except: + discard tox.send(friend, getCurrentExceptionMsg(), TOX_MESSAGE_TYPE_ACTION) + tox.name = "blobbot" - echo "callbacks set" - echo "Tox address: ", tox.address - echo "Tox DHT: ", tox.udpPort, " ", tox.dhtId + echo "/connect 127.0.0.1 ", tox.udpPort, " ", tox.dhtId + echo "/add ", tox.address proc toxMain() {.async.} = let tox = newTox do (o: Options):