1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- ;; SPDX-FileCopyrightText: 2021 pukkamustard <pukkamustard@posteo.net>
- ;; SPDX-FileCopyrightText: 2022 Maxime Devos <maximedevos@telenet.be>
- ;;
- ;; SPDX-License-Identifier: AGPL-3.0-or-later
- ;; This module provides an interface to the GNUnet DHT service for storing and
- ;; retrieving blocks. This can be used to store blocks of ERIS encoded content.
- ;; TODO: the FS service has some fanciness w.r.t. reputation and not storing
- ;; everything on DHT directly, instead contacting relevant peers with CADET.
- ;;
- ;; Scheme-GNUnet is AGPL, so this module is AGPL (and not GPL) too.
- (define-module (eris blocks gnunet-dht)
- #:use-module (gnu gnunet config fs)
- #:use-module (gnu gnunet dht client)
- #:use-module (gnu gnunet utils bv-slice)
- #:use-module (gnu gnunet netstruct syntactic)
- #:use-module (gnu gnunet hashcode struct)
- #:use-module (fibers conditions)
- #:use-module (srfi srfi-71)
- #:use-module (rnrs bytevectors)
- #:export (eris-gnunet-dht-server
- eris-blocks-gnunet-dht-reducer
- eris-blocks-gnunet-dht-ref))
- ;; Connection to the DHT service, made with 'connect'
- ;; from (gnu gnunet dht client)
- (define eris-gnunet-dht-server (make-parameter #f))
- (define (current-dht-server)
- (or (eris-gnunet-dht-server)
- (error "not connected to the DHT service, set 'eris-gnunet-dht-server'!'")))
- ;; TODO: register a dedicated block type instead of using
- ;; block:test
- (define eris-block-type 8)
- (define (reference->dht-key ref)
- (define key/extended (make-slice/read-write (sizeof /hashcode:512 '())))
- (slice-copy! (bv-slice/read-write ref)
- (slice-slice key/extended 0 (bytevector-length ref)))
- (slice/read-only key/extended))
- (define (gnunet-block-put key value)
- "Store a block on GNUnet's DHT."
- ;; TODO: set the expiration time and replication level appropriately.
- ;; TODO: make-datum and put! assume that the bytevector slice isn't modified
- ;; until it is sent; verify that 'value' aren't modified or make a copy.
- (put! (current-dht-server)
- (datum->insertion
- (make-datum eris-block-type
- (reference->dht-key key)
- (bv-slice/read-write value)))))
- ;; GNUnet block reducer
- (define eris-blocks-gnunet-dht-reducer
- (case-lambda
- ;; Initialization. Nothing to do here. In an improved implementation,
- ;; we might want to limit the number of blocks that are currently
- ;; being sent to the service, to keep memory usage from growing
- ;; indefinitely when the service is slow.
- (() '())
- ;; Completion. Again, nothing to do.
- ((_) 'done)
- ;; store a block
- ((_ ref-block)
- (gnunet-block-put (car ref-block) (cdr ref-block)))))
- (define (eris-blocks-gnunet-dht-ref ref)
- "Dereference a block from GNUnet's DHT"
- ;; TODO: implement timeouts!
- ;; TODO: it would be nice if guile-eris could fetch multiple blocks
- ;; in parallel.
- (define query
- (make-query eris-block-type (reference->dht-key ref)))
- (define response)
- (define received (make-condition))
- (define (found search-result)
- ;; TODO: verify the value matches the key.
- ;; A malicious peer or a peer with broken memory
- ;; could put invalid key->value mappings into the DHT,
- ;; which should ideally be ignored in favour of correct
- ;; mappings ...
- (define value (datum-value (search-result->datum search-result)))
- (define value/bv (make-bytevector (slice-length value)))
- (slice-copy! value (bv-slice/read-write value/bv))
- (set! response value/bv)
- (signal-condition! received))
- (define get-handle (start-get! (current-dht-server) query found))
- (wait received)
- ;; TODO: cancel the get-handle to avoid leaking memory
- ;; (not yet implemented in gnunet-scheme ...)
- response)
|