syndicate_actor_tox/src/tox_eris_ingester.nim

64 lines
2.1 KiB
Nim

# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[asyncdispatch, asyncfile, logging, strutils]
from std/os import `/`, getTempDir, lastPathPart, removeFile
import preserves, syndicate
import eris
import ./protocol
addHandler(newConsoleLogger(useStderr = true))
# register global logger to stderr
proc ingestFile(
friend, transfer: Ref; sinkHandle: Handle;
store: ErisStore; path: string; fileSize: uint64) {.async.} =
var
file = openAsync(path, fmRead)
count: uint64
if file.getFileSize.uint64 == fileSize:
var
blockSize = recommendedBlockSize(fileSize)
buf = newSeq[byte](blockSize.int)
ingest = newErisIngest(store, blockSize)
while count < fileSize and buf.len > 0:
buf.setLen(await readBuffer(file, addr buf[0], buf.len))
await ingest.append(buf)
count.inc buf.len
if count == fileSize:
var
cap = await ingest.cap
fileName = path.lastPathPart
urn = $cap & "&dn=" & filename & "&xl=" & $fileSize
run(friend) do (turn: var Turn):
let ass = MessageSend(body: urn)
message(turn, friend, ass)
info "close and remove ", path
close(file)
removeFile(path)
if count != fileSize:
error "failed to ingest ", path, ", read ", count, " bytes of ", fileSize
run(transfer) do (turn: var Turn):
info "retract sink handle"
retract(turn, sinkHandle)
bootDataspace("main") do (root: Ref; turn: var Turn):
connectStdio(root, turn)
during(turn, root, FriendDataspace[Ref] ? { 1: grab() }) do (friend: Ref):
info "got a friend ref ", friend
during(turn, friend, ?TransferDataspace[Ref]) do (
kind: int, size: uint64, filename: string, transfer: Ref):
info "got a transfer for ", filename
let
path = getTempDir() / filename
sinkHandle = publish(turn, transfer, TransferSink(path: path))
onPublish(turn, transfer, ?Completion) do:
asyncCheck ingestFile(friend, transfer, sinkHandle, newDiscardStore(), path, size)
do:
info "transfer retracted"
do:
info "friend retracted"
runForever()