64 lines
2.1 KiB
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()
|