ddat interop with dat js cable interop with cabal js ddat's frontend = dat-thang cable fe = cable-thang dillo support based on cel's dillo-dat bootstrap node xplatform support Signed-off-by: divo <418@cryspace.space>
152 lines
5.3 KiB
C
152 lines
5.3 KiB
C
#ifndef DAT_SESSION_H
|
|
#define DAT_SESSION_H
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include "cesspool.h"
|
|
#include "dat.h"
|
|
#include "dat_wire.h"
|
|
#include "sleep_feed.h"
|
|
#include "sleep_replication.h"
|
|
|
|
#define DAT_SESSION_MAX_PEERS 64u
|
|
#define DAT_SESSION_CAP_METADATA_ONLY (UINT64_C(1) << 63)
|
|
|
|
enum dat_session_state {
|
|
DAT_SESSION_CLOSED = 0,
|
|
DAT_SESSION_OPEN = 1,
|
|
DAT_SESSION_DISCOVERING = 2,
|
|
DAT_SESSION_ACTIVE = 3,
|
|
DAT_SESSION_CLOSING = 4,
|
|
DAT_SESSION_FAILED = 5
|
|
};
|
|
|
|
enum dat_session_peer_state {
|
|
DAT_SESSION_PEER_DISCOVERED = 1,
|
|
DAT_SESSION_PEER_SECURE = 2,
|
|
DAT_SESSION_PEER_READY = 3,
|
|
DAT_SESSION_PEER_CLOSED = 4
|
|
};
|
|
|
|
enum dat_session_feed {
|
|
DAT_SESSION_METADATA = 0,
|
|
DAT_SESSION_CONTENT = 1,
|
|
DAT_SESSION_FEED_COUNT = 2
|
|
};
|
|
|
|
typedef struct dat_session_peer {
|
|
uint8_t peer_id[DAT_PEER_ID_BYTES];
|
|
uint8_t tx_nonce[24];
|
|
uint8_t rx_nonce[24];
|
|
uint8_t *rx_buffer;
|
|
size_t rx_buffer_len;
|
|
size_t rx_buffer_capacity;
|
|
uint64_t tx_offset;
|
|
uint64_t rx_offset;
|
|
uint8_t remote_feed_mask;
|
|
uint8_t local_feed_mask;
|
|
uint8_t remote_content_discovery[32];
|
|
int remote_content_pending;
|
|
dat_peer_t address;
|
|
uint64_t capabilities;
|
|
uint64_t payload_bytes_sent;
|
|
uint64_t payload_bytes_received;
|
|
int state;
|
|
int transport_authenticated;
|
|
int paused;
|
|
int tx_stream_encrypted;
|
|
int rx_stream_encrypted;
|
|
sleep_replication_t replication[DAT_SESSION_FEED_COUNT];
|
|
} dat_session_peer_t;
|
|
|
|
struct dat_session;
|
|
typedef int (*dat_session_send_fn)(void *context,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES],
|
|
const uint8_t *frame, size_t frame_len);
|
|
typedef int (*dat_session_request_fn)(void *context,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES],
|
|
enum dat_session_feed feed,
|
|
const dat_request_t *request);
|
|
/* Called when discovery yields a peer; establish an authenticated transport,
|
|
* then report success with dat_session_peer_secure(). */
|
|
typedef void (*dat_session_peer_fn)(void *context,
|
|
const dat_session_peer_t *peer);
|
|
typedef int (*dat_session_poll_fn)(void *context, int timeout_ms);
|
|
|
|
/*
|
|
* Session protocol state is separate from connection establishment. In the
|
|
* Cesspool path, call peer_secure only after the authenticated transport has
|
|
* bound this peer ID to the topic. In legacy Hypercore V6 mode, call it once
|
|
* the discovered TCP/uTP stream is connected; V6 performs its feed-key stream
|
|
* encryption inside the protocol itself.
|
|
*/
|
|
typedef struct dat_session {
|
|
int state;
|
|
int announcing;
|
|
int looking_up;
|
|
uint16_t port;
|
|
uint8_t archive_key[DAT_KEY_BYTES];
|
|
uint8_t discovery_topic[CESSPOOL_TOPIC_BYTES];
|
|
uint8_t peer_id[DAT_PEER_ID_BYTES];
|
|
uint8_t feed_keys[DAT_SESSION_FEED_COUNT][DAT_KEY_BYTES];
|
|
int content_key_known;
|
|
cesspool_t *cesspool;
|
|
sleep_feed_t *feeds[DAT_SESSION_FEED_COUNT];
|
|
dat_session_peer_t peers[DAT_SESSION_MAX_PEERS];
|
|
size_t peer_count;
|
|
dat_session_send_fn send;
|
|
dat_session_request_fn on_request;
|
|
dat_session_peer_fn on_peer;
|
|
void *peer_context;
|
|
dat_session_poll_fn poll_transport;
|
|
void *poll_context;
|
|
void *context;
|
|
} dat_session_t;
|
|
|
|
int dat_session_init(dat_session_t *session, cesspool_t *cesspool,
|
|
const uint8_t archive_key[DAT_KEY_BYTES],
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES], uint16_t port,
|
|
sleep_feed_t *metadata_feed,
|
|
const uint8_t metadata_key[DAT_KEY_BYTES],
|
|
sleep_feed_t *content_feed,
|
|
const uint8_t content_key[DAT_KEY_BYTES],
|
|
dat_session_send_fn send, void *context);
|
|
int dat_session_start(dat_session_t *session, int announce, int lookup);
|
|
int dat_session_set_peer_callback(dat_session_t *session,
|
|
dat_session_peer_fn callback, void *context);
|
|
int dat_session_set_transport_poll(dat_session_t *session,
|
|
dat_session_poll_fn poll, void *context);
|
|
int dat_session_peer_discovered(dat_session_t *session,
|
|
const cesspool_peer_t *discovered_peer);
|
|
int dat_session_peer_secure(dat_session_t *session,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES],
|
|
int transport_authenticated);
|
|
/* For a metadata-only archive import, install the content key learned from
|
|
* the verified metadata header and announce that feed to connected peers. */
|
|
int dat_session_set_content_key(dat_session_t *session,
|
|
const uint8_t content_key[DAT_KEY_BYTES]);
|
|
int dat_session_expect_content_key(dat_session_t *session);
|
|
int dat_session_peer_down(dat_session_t *session,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES]);
|
|
/* Pause this client's incoming block requests without dropping the peer. */
|
|
int dat_session_peer_pause(dat_session_t *session,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES], int paused);
|
|
/* Accept arbitrary transport chunks. Partial and coalesced wire frames are buffered. */
|
|
int dat_session_receive(dat_session_t *session,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES],
|
|
const uint8_t *frame, size_t frame_len);
|
|
int dat_session_request_block(dat_session_t *session,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES],
|
|
enum dat_session_feed feed, uint64_t index,
|
|
uint64_t bytes);
|
|
int dat_session_send_block(dat_session_t *session,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES],
|
|
enum dat_session_feed feed, uint64_t index);
|
|
int dat_session_tick(dat_session_t *session, uint64_t now_ms);
|
|
int dat_session_poll(dat_session_t *session, int timeout_ms, uint64_t now_ms);
|
|
int dat_session_close(dat_session_t *session);
|
|
dat_session_peer_t *dat_session_find_peer(dat_session_t *session,
|
|
const uint8_t peer_id[DAT_PEER_ID_BYTES]);
|
|
|
|
#endif /* DAT_SESSION_H */
|