#ifndef DAT_SESSION_H #define DAT_SESSION_H #include #include #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 */