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>
This commit is contained in:
divorce committed 2026-10-19 00:17:02 -04:00
1 parent f0f91540be
commit b735900f2e
323 files changed
+134347 -343

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
#ifndef BASE32768_H
#define BASE32768_H
#include <stddef.h>
#include <stdint.h>
/* UTF-8 C-string form of qntm/base32768's BMP-safe Base32768 encoding. */
int base32768_encode(const uint8_t *input, size_t input_length,
char *output, size_t output_capacity);
int base32768_decode(const char *input, uint8_t *output,
size_t output_capacity, size_t *output_length);
/* Enumerate the alphabet: bits=15 selects the 32,768 main characters;
* bits=7 selects the 128 possible final padding characters. */
int base32768_codepoint_at(unsigned bits, uint32_t index, uint32_t *codepoint);
#endif
+81
View File
@@ -0,0 +1,81 @@
#ifndef CABLE_H
#define CABLE_H
#include <stddef.h>
#include <stdint.h>
#include "keys.h"
#include "sleep_feed.h"
#define CABLE_KEY_BYTES 32u
#define CABLE_CHAT_TEXT_BYTES 768u
#define CABLE_CHAT_WIRE_BYTES (4u + 8u + 2u + CABLE_CHAT_TEXT_BYTES)
#define CABLE_CHAT_SEAL_BYTES (CABLE_CHAT_WIRE_BYTES + 48u)
enum cable_address_scheme {
CABLE_ADDRESS_CABAL = 1,
CABLE_ADDRESS_CABLE = 2,
CABLE_ADDRESS_HYPER = 3
};
typedef struct cable_chat_message {
uint64_t timestamp_ms;
char text[CABLE_CHAT_TEXT_BYTES + 1u];
size_t text_length;
} cable_chat_message_t;
/* A Cabal user address is that user's persistent feed public key. A room
* address may additionally carry a room moderation/admin key. */
typedef struct cable_room_address {
uint8_t key[CABLE_KEY_BYTES];
uint8_t admin_key[CABLE_KEY_BYTES];
enum cable_address_scheme scheme;
int has_admin;
} cable_room_address_t;
/* The schemes share a 32-byte key representation; the caller decides whether
* it is a room key or a user feed key. hyper:// is a migration alias only. */
int cable_address_parse(const char *address, uint8_t key[CABLE_KEY_BYTES],
enum cable_address_scheme *scheme);
int cable_address_format(const uint8_t key[CABLE_KEY_BYTES],
enum cable_address_scheme scheme, char *out, size_t capacity);
int cable_room_address_parse(const char *address, cable_room_address_t *room);
int cable_room_address_format(const cable_room_address_t *room,
enum cable_address_scheme scheme, char *out, size_t capacity);
int cable_user_address_format(const uint8_t user_feed_key[CABLE_KEY_BYTES],
enum cable_address_scheme scheme, char *out, size_t capacity);
/* Cabal stores the local writer in a room's storage, so derive a per-room
* local feed-key path instead of sharing one global identity across rooms. */
int cable_user_identity_path(const char *home,
const uint8_t room_key[CABLE_KEY_BYTES],
char *out, size_t capacity);
/* Create a Cabal room signing key and persist it in the room directory. */
int cable_room_create(const char *home, uint8_t room_key[CABLE_KEY_BYTES]);
/* Store/load the user's local feed secret key. The public key is derived and
* checked on load. The file contains only the 64-byte Ed25519 secret key. */
int cable_user_identity_load_or_create(const char *path, sleep_keypair_t *identity);
/* Cabal stores messages as JSON blocks in each user's Hypercore feed. These
* helpers use the same Hypercore 7.x on-disk tree/signature layout. */
int cable_user_feed_open(const char *home,
const uint8_t room_key[CABLE_KEY_BYTES],
sleep_keypair_t *identity, sleep_feed_t *feed);
int cable_user_feed_append(const char *home,
const uint8_t room_key[CABLE_KEY_BYTES],
const uint8_t *record, size_t record_length,
uint8_t user_key[CABLE_KEY_BYTES]);
int cable_user_feed_publish(const char *home,
const uint8_t room_key[CABLE_KEY_BYTES],
const char *record_type, const char *nick,
const char *channel, const char *text,
uint8_t user_key[CABLE_KEY_BYTES]);
int cable_chat_message_encode(const cable_chat_message_t *message,
uint8_t *out, size_t capacity, size_t *written);
int cable_chat_message_decode(cable_chat_message_t *message,
const uint8_t *input, size_t length);
int cable_chat_seal(const uint8_t recipient_ed25519[32],
const uint8_t *message, size_t message_length,
uint8_t *out, size_t capacity, size_t *written);
int cable_chat_open(const sleep_keypair_t *identity,
const uint8_t *sealed, size_t sealed_length,
uint8_t *out, size_t capacity, size_t *written);
#endif
+56
View File
@@ -0,0 +1,56 @@
#ifndef CABLE_MEDIA_H
#define CABLE_MEDIA_H
#include <stddef.h>
#include <stdint.h>
#define CABLE_MEDIA_SESSION_BYTES 16u
#define CABLE_MEDIA_HEADER_BYTES 42u
#define CABLE_MEDIA_MAX_PACKET_BYTES 4096u
#define CABLE_MEDIA_AAC_RATE 48000u
#define CABLE_MEDIA_AAC_BITRATE 96000u
#define CABLE_MEDIA_AAC_CHANNELS 1u
#define CABLE_MEDIA_AAC_SAMPLES 1024u
enum cable_media_kind {
CABLE_MEDIA_AUDIO_START = 1,
CABLE_MEDIA_AUDIO_FRAME = 2,
CABLE_MEDIA_AUDIO_STOP = 3,
CABLE_MEDIA_VIDEO_START = 4,
CABLE_MEDIA_VIDEO_FRAME = 5,
CABLE_MEDIA_VIDEO_STOP = 6
};
typedef struct cable_media_packet {
uint8_t kind;
uint8_t session[CABLE_MEDIA_SESSION_BYTES];
uint64_t sequence;
uint64_t timestamp_us;
const uint8_t *payload;
size_t payload_length;
} cable_media_packet_t;
int cable_media_packet_write(const cable_media_packet_t *packet,
uint8_t *output, size_t capacity, size_t *written);
int cable_media_packet_read(cable_media_packet_t *packet,
const uint8_t *input, size_t length);
typedef struct cable_aac_encoder { void *implementation; } cable_aac_encoder_t;
typedef struct cable_aac_decoder { void *implementation; } cable_aac_decoder_t;
typedef int (*cable_aac_frame_fn)(void *context, const uint8_t *adts,
size_t length);
typedef int (*cable_pcm_samples_fn)(void *context, const int16_t *samples,
size_t sample_count);
int cable_aac_encoder_open(cable_aac_encoder_t *encoder);
int cable_aac_encoder_frame(cable_aac_encoder_t *encoder,
const int16_t samples[CABLE_MEDIA_AAC_SAMPLES],
cable_aac_frame_fn output, void *context);
void cable_aac_encoder_close(cable_aac_encoder_t *encoder);
int cable_aac_decoder_open(cable_aac_decoder_t *decoder);
int cable_aac_decoder_frame(cable_aac_decoder_t *decoder,
const uint8_t *adts, size_t length,
cable_pcm_samples_fn output, void *context);
void cable_aac_decoder_close(cable_aac_decoder_t *decoder);
#endif
+30
View File
@@ -0,0 +1,30 @@
#ifndef CABLE_ROOM_H
#define CABLE_ROOM_H
#include "cable.h"
#define CABLE_ROOM_CHANNEL_BYTES 64u
#define CABLE_ROOM_NICK_BYTES 64u
enum cable_room_event_type {
CABLE_ROOM_PEER_JOIN = 1,
CABLE_ROOM_PEER_LEAVE = 2,
CABLE_ROOM_NICK = 3,
CABLE_ROOM_CHANNEL_JOIN = 4,
CABLE_ROOM_TEXT = 5
};
typedef struct cable_room_event {
uint8_t type;
uint64_t timestamp_ms;
uint8_t sender[CABLE_KEY_BYTES];
char channel[CABLE_ROOM_CHANNEL_BYTES + 1u];
char nick[CABLE_ROOM_NICK_BYTES + 1u];
char text[CABLE_CHAT_TEXT_BYTES + 1u];
size_t text_length;
} cable_room_event_t;
/* In-memory UI event only. Cable's network records are Cabal Core Hypercore
* values and never serialize this C structure. */
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef CABLE_VIDEO_H
#define CABLE_VIDEO_H
#include <stddef.h>
#include <stdint.h>
typedef struct cable_video_source cable_video_source_t;
/* Read an OBS MPEG-TS feed from a local UDP socket, normally port 5000.
* Pixels are copied as RGB24; a generation change means a new frame arrived. */
cable_video_source_t *cable_video_source_open(const char *url);
void cable_video_source_close(cable_video_source_t *source);
int cable_video_source_frame(cable_video_source_t *source, uint8_t *rgb,
size_t capacity, unsigned *width, unsigned *height,
uint64_t *generation);
/* Encode/decode one low-resolution JPEG frame for volatile Cable media. */
int cable_video_encode_jpeg(const uint8_t *rgb, unsigned width, unsigned height,
uint8_t *jpeg, size_t capacity, size_t *written);
int cable_video_decode_jpeg(const uint8_t *jpeg, size_t length, uint8_t *rgb,
size_t capacity, unsigned *width, unsigned *height);
#endif
+7 -12
View File
@@ -1,14 +1,9 @@
#ifndef CESSPOOL_H
#define CESSPOOL_H
#ifndef CESSPOOL_COMPAT_H
#define CESSPOOL_COMPAT_H
#include "key.h"
/* Compatibility include for existing Dat/Cable modules. The public Cesspool
* API and its independent network types live in libcess/include. */
#include <libcess/cesspool.h>
#include "dat_net.h"
// bootstrap node
// dht
// discovery
// lookup (key) ↳ lookup1
// announce
// ping
// holepunch udp
#endif /* CESSPOOL_H */
#endif
+110
View File
@@ -1,4 +1,114 @@
#ifndef DAT_H
#define DAT_H
#include <stdint.h>
#include <stddef.h>
#include "keys.h"
#include "sleep_proto.h"
#define DAT_KEY_BYTES 32u
#define DAT_BLOCK_BYTES (64u * 1024u)
#define DAT_URL_BYTES 71u
#define DAT_LINK_BYTES 4096u
typedef struct dat_archive {
char dat_path[1024];
uint8_t metadata_key[DAT_KEY_BYTES];
uint8_t content_key[DAT_KEY_BYTES];
sleep_keypair_t metadata_keys;
sleep_keypair_t content_keys;
} dat_archive_t;
typedef struct dat_link {
uint8_t key[DAT_KEY_BYTES];
uint64_t version;
int has_version;
char path[2048];
} dat_link_t;
typedef struct dat_checkout {
const dat_archive_t *archive;
uint64_t version;
} dat_checkout_t;
typedef struct dat_url {
char host[256];
char path[2048];
uint64_t version;
int has_version;
int wants_stat;
int force_directory_listing;
} dat_url_t;
typedef struct dat_path_info {
sleep_metadata_entry_t entry;
int exists;
int is_directory;
} dat_path_info_t;
typedef int (*dat_archive_change_fn)(const sleep_metadata_entry_t *entry,
uint64_t version, void *context);
typedef int (*dat_archive_readdir_fn)(const sleep_metadata_entry_t *entry,
const char *name, void *context);
/* Creates a new two-feed legacy-style archive skeleton under root/.dat. */
int dat_archive_create(dat_archive_t *archive, const char *root);
int dat_archive_open(dat_archive_t *archive, const char *root);
int dat_archive_open_writable(dat_archive_t *archive, const char *root,
const char *secret_directory);
int dat_archive_save_secrets(const dat_archive_t *archive,
const char *secret_directory);
void dat_archive_close(dat_archive_t *archive);
size_t dat_archive_entry_count(const dat_archive_t *archive);
uint64_t dat_archive_version(const dat_archive_t *archive);
int dat_archive_append_file(dat_archive_t *archive, const char *path,
const uint8_t *data, size_t length,
uint32_t mode, uint64_t mtime);
int dat_archive_append_directory(dat_archive_t *archive, const char *path,
uint32_t mode, uint64_t mtime);
int dat_archive_append_symlink(dat_archive_t *archive, const char *path,
const char *target, uint64_t mtime);
int dat_archive_delete(dat_archive_t *archive, const char *path, uint64_t mtime);
int dat_archive_read_entry(const dat_archive_t *archive, size_t index,
sleep_metadata_entry_t *entry);
int dat_archive_read_file(const dat_archive_t *archive,
const sleep_metadata_entry_t *entry,
uint8_t **data, size_t *length);
int dat_archive_find(const dat_archive_t *archive, const char *path,
sleep_metadata_entry_t *entry);
int dat_archive_find_at(const dat_archive_t *archive, const char *path,
uint64_t version, sleep_metadata_entry_t *entry);
int dat_checkout_init(dat_checkout_t *checkout, const dat_archive_t *archive,
uint64_t version);
int dat_checkout_find(const dat_checkout_t *checkout, const char *path,
sleep_metadata_entry_t *entry);
int dat_checkout_read(const dat_checkout_t *checkout,
const sleep_metadata_entry_t *entry,
uint8_t **data, size_t *length);
int dat_checkout_export(const dat_checkout_t *checkout, const char *archive_path,
const char *filesystem_path);
int dat_archive_changes(const dat_archive_t *archive, uint64_t from_version,
uint64_t to_version, dat_archive_change_fn callback, void *context);
int dat_archive_stat_at(const dat_archive_t *archive, uint64_t version,
const char *path, dat_path_info_t *info);
int dat_archive_readdir_at(const dat_archive_t *archive, uint64_t version,
const char *path, dat_archive_readdir_fn callback,
void *context);
int dat_archive_resolve_at(const dat_archive_t *archive, uint64_t version,
const char *path, int force_directory_listing,
dat_path_info_t *info, int *serve_directory_listing);
const char *dat_content_type(const char *path);
int dat_url_parse(const char *text, dat_url_t *url);
int dat_archive_import_path(dat_archive_t *archive, const char *filesystem_path,
const char *archive_path);
/* Imports only changed paths and records tombstones for paths removed locally. */
int dat_archive_sync_path(dat_archive_t *archive, const char *filesystem_path,
const char *archive_path);
int dat_archive_export_path(const dat_archive_t *archive, const char *archive_path,
const char *filesystem_path);
int dat_archive_export_at(const dat_archive_t *archive, uint64_t version,
const char *archive_path, const char *filesystem_path);
int dat_key_to_url(const uint8_t key[DAT_KEY_BYTES], char url[DAT_URL_BYTES]);
int dat_key_to_compact_url(const uint8_t key[DAT_KEY_BYTES], char url[DAT_URL_BYTES]);
int dat_key_to_hex(const uint8_t key[DAT_KEY_BYTES], char hex[65]);
int dat_url_to_key(const char *url, uint8_t key[DAT_KEY_BYTES]);
int dat_link_format(const dat_link_t *link, char *out, size_t capacity);
int dat_link_format_compact(const dat_link_t *link, char *out, size_t capacity);
int dat_link_parse(const char *text, dat_link_t *link);
#endif /* DAT_H */
+27
View File
@@ -0,0 +1,27 @@
#ifndef DAT_DNS_H
#define DAT_DNS_H
#include <stdint.h>
#include "dat.h"
typedef int (*dat_dns_name_iter_fn)(const char *hostname,
const uint8_t key[DAT_KEY_BYTES], void *context);
/* Resolve a legacy Dat DNS TXT record such as datkey=<64 hex digits>. */
int dat_dns_resolve(const char *hostname, uint8_t key[DAT_KEY_BYTES],
uint32_t *ttl_seconds);
/* Local dat-dns aliases are stored in $HOME/.dat/dat-dns (or USERPROFILE on
* native Windows) and override DNS TXT. */
int dat_dns_name_set(const char *hostname, const uint8_t key[DAT_KEY_BYTES]);
int dat_dns_name_remove(const char *hostname);
int dat_dns_name_resolve(const char *hostname, uint8_t key[DAT_KEY_BYTES]);
int dat_dns_name_for_key(const uint8_t key[DAT_KEY_BYTES], char *hostname,
size_t hostname_capacity);
int dat_dns_name_foreach(dat_dns_name_iter_fn callback, void *context);
/* Decode TXT record character strings from one DNS answer packet. */
int dat_dns_parse_answer(const uint8_t *packet, unsigned packet_len,
uint8_t key[DAT_KEY_BYTES], uint32_t *ttl_seconds);
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef DAT_FETCH_H
#define DAT_FETCH_H
#include <stdint.h>
/* Fetch the public metadata and content feeds for a Dat key into root/.dat.
* The fetch uses the configured Cesspool network and persists verified sparse
* feed blocks so a later Dillo request can resume it. */
int dat_fetch_archive(const char *root, const uint8_t metadata_key[32],
unsigned timeout_ms);
#endif
+18 -29
View File
@@ -1,33 +1,22 @@
#ifndef DAT_NET_H
#define DAT_NET_H
#ifndef DAT_NET_COMPAT_H
#define DAT_NET_COMPAT_H
#include <stdint.h>
#include <stddef.h>
#include <sys/socket.h>
/* Source-compatibility names for Dat/Cable code written before libcess was
* extracted. New integrations should include <cess_net.h> directly. */
#include <libcess/cess_net.h>
#include "dat_socket.h"
#define DATNET_PORT 3282
#define DATNET_MAX_PACKET 1400
#define DATNET_TOPIC_BYTES 32
#define DATNET_PEERID_BYTES 32
typedef cess_peer_t dat_peer_t;
typedef cessnet_t datnet_t;
typedef struct {
int fd;
struct sockaddr_storage addr;
socklen_t addrlen;
uint8_t id[DATNET_PEERID_BYTES];
} dat_peer_t;
#define DATNET_PORT CESSNET_PORT
#define DATNET_MAX_PACKET CESSNET_MAX_PACKET
#define DATNET_TOPIC_BYTES CESSNET_TOPIC_BYTES
#define DATNET_PEERID_BYTES CESSNET_PEERID_BYTES
#define datnet_init cessnet_init
#define datnet_bind cessnet_bind
#define datnet_poll cessnet_poll
#define datnet_send cessnet_send
#define datnet_close cessnet_close
typedef struct {
int sock;
uint8_t topic[DATNET_TOPIC_BYTES];
uint8_t peerid[DATNET_PEERID_BYTES];
void (*on_message)(dat_peer_t *peer, const uint8_t *msg, size_t len);
} datnet_t;
int datnet_init();
int datnet_bind();
int datnet_poll();
int datnet_send();
int datnet_close(datnet_t *net);
#endif /* DAT_NET_H */
#endif
+48
View File
@@ -0,0 +1,48 @@
#ifndef DAT_PATHS_H
#define DAT_PATHS_H
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#endif
/* Return the user's home directory across POSIX shells and native Windows
* launches. Windows GUI starts commonly have USERPROFILE but no HOME. */
static inline const char *dat_home_directory(void)
{
const char *home = getenv("HOME");
if (home && *home) return home;
#ifdef _WIN32
home = getenv("USERPROFILE");
if (home && *home) return home;
{
const char *drive = getenv("HOMEDRIVE");
const char *path = getenv("HOMEPATH");
static char combined[1024];
int n;
if (!drive || !*drive || !path || !*path) return NULL;
n = snprintf(combined, sizeof(combined), "%s%s", drive, path);
return n >= 0 && (size_t)n < sizeof(combined) ? combined : NULL;
}
#else
return NULL;
#endif
}
/* POSIX rename replaces an existing file; Windows rename does not. These
* state files are written to a sibling temporary file before replacement. */
static inline int dat_replace_file(const char *temporary, const char *destination)
{
#ifdef _WIN32
if (MoveFileExA(temporary, destination,
MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) return 0;
errno = EIO;
return -1;
#else
return rename(temporary, destination);
#endif
}
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef DAT_S7_H
#define DAT_S7_H
#include "s7.h"
#include "dat.h"
typedef struct dat_scheme_runtime {
s7_scheme *scheme;
} dat_scheme_runtime_t;
int dat_s7_init(s7_scheme *scheme);
int dat_scheme_runtime_init(dat_scheme_runtime_t *runtime);
void dat_scheme_runtime_close(dat_scheme_runtime_t *runtime);
int dat_scheme_write_archive_info(s7_scheme *scheme, const char *root,
const dat_archive_t *archive,
const char *title, const char *description,
int replace);
#endif
+151
View File
@@ -0,0 +1,151 @@
#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 */
+18
View File
@@ -0,0 +1,18 @@
#ifndef DAT_SOCKET_H
#define DAT_SOCKET_H
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
typedef SOCKET dat_socket_t;
#define DAT_INVALID_SOCKET INVALID_SOCKET
#else
#include <sys/socket.h>
typedef int dat_socket_t;
#define DAT_INVALID_SOCKET (-1)
#endif
#endif
+110
View File
@@ -0,0 +1,110 @@
#ifndef DAT_WIRE_H
#define DAT_WIRE_H
#include <stddef.h>
#include <stdint.h>
enum dat_message_type {
DAT_MSG_FEED = 0,
DAT_MSG_HANDSHAKE = 1,
DAT_MSG_INFO = 2,
DAT_MSG_HAVE = 3,
DAT_MSG_UNHAVE = 4,
DAT_MSG_WANT = 5,
DAT_MSG_UNWANT = 6,
DAT_MSG_REQUEST = 7,
DAT_MSG_CANCEL = 8,
DAT_MSG_DATA = 9,
DAT_MSG_EXTENSION = 15
};
typedef struct dat_feed_open {
uint8_t discovery_key[32];
uint8_t nonce[24];
int has_nonce;
} dat_feed_open_t;
typedef struct dat_wire_message {
uint64_t channel;
uint64_t type;
const uint8_t *payload;
size_t payload_len;
} dat_wire_message_t;
#define DAT_PROTOCOL_BYTES 32u
#define DAT_PEER_ID_BYTES 32u
#ifndef DAT_NETWORK_PROTOCOL
#define DAT_NETWORK_PROTOCOL "cesspool"
#endif
/*
* The exact protocol token lives in the repository-root NETWORK_PROTOCOL
* file. The Cesspool handshake carries it in `userData`; legacy Hypercore V6
* omits that application-owned field and uses the token to select its
* discovery namespace and wire mode. This checkout defaults to `cesspool`.
*/
typedef struct dat_handshake {
uint8_t protocol[DAT_PROTOCOL_BYTES];
uint8_t peer_id[DAT_PEER_ID_BYTES];
uint64_t capabilities;
int has_peer_id;
} dat_handshake_t;
int dat_handshake_init(dat_handshake_t *handshake,
const uint8_t peer_id[DAT_PEER_ID_BYTES],
uint64_t capabilities);
int dat_handshake_protocol_matches(const dat_handshake_t *handshake);
typedef struct dat_range { uint64_t start; uint64_t length; } dat_range_t;
typedef struct dat_info { uint8_t uploading; uint8_t downloading; } dat_info_t;
typedef struct dat_request { uint64_t index; uint64_t bytes; uint8_t want_hash; uint8_t want_nodes; } dat_request_t;
#define DAT_DATA_MAX_NODES 128u
typedef struct dat_data_node {
uint64_t index;
uint64_t length;
uint8_t hash[32];
} dat_data_node_t;
typedef struct dat_data {
uint64_t index;
const uint8_t *value;
size_t value_len;
const uint8_t *proof;
size_t proof_len;
dat_data_node_t nodes[DAT_DATA_MAX_NODES];
size_t node_count;
uint8_t signature[64];
int has_signature;
} dat_data_t;
typedef struct dat_cancel { uint64_t index; } dat_cancel_t;
typedef struct dat_extension {
uint64_t id;
const uint8_t *message;
size_t message_len;
} dat_extension_t;
/* Hypercore frames are length-prefixed; headers pack channel and type. */
int dat_wire_encode(const dat_wire_message_t *message, uint8_t *out,
size_t capacity, size_t *written);
int dat_wire_decode(dat_wire_message_t *message, const uint8_t *input,
size_t input_len, size_t *consumed);
int dat_handshake_encode(const dat_handshake_t *handshake, uint8_t *out,
size_t capacity, size_t *written);
int dat_handshake_decode(dat_handshake_t *handshake, const uint8_t *input,
size_t input_len);
int dat_feed_open_encode(const dat_feed_open_t *feed, uint8_t *out,
size_t capacity, size_t *written);
int dat_feed_open_decode(dat_feed_open_t *feed, const uint8_t *input,
size_t input_len);
int dat_range_encode(const dat_range_t *range, uint8_t *out, size_t capacity, size_t *written);
int dat_range_decode(dat_range_t *range, const uint8_t *input, size_t input_len);
/* WANT omits length to mean through the current end of a non-live feed. */
int dat_want_decode(dat_range_t *range, const uint8_t *input, size_t input_len,
uint64_t feed_length);
int dat_info_encode(const dat_info_t *info, uint8_t *out, size_t capacity,
size_t *written);
int dat_info_decode(dat_info_t *info, const uint8_t *input, size_t input_len);
int dat_request_encode(const dat_request_t *request, uint8_t *out, size_t capacity, size_t *written);
int dat_request_decode(dat_request_t *request, const uint8_t *input, size_t input_len);
int dat_data_encode(const dat_data_t *data, uint8_t *out, size_t capacity, size_t *written);
int dat_data_decode(dat_data_t *data, const uint8_t *input, size_t input_len);
int dat_cancel_encode(const dat_cancel_t *cancel, uint8_t *out, size_t capacity, size_t *written);
int dat_cancel_decode(dat_cancel_t *cancel, const uint8_t *input, size_t input_len);
int dat_extension_encode(const dat_extension_t *extension, uint8_t *out, size_t capacity, size_t *written);
int dat_extension_decode(dat_extension_t *extension, const uint8_t *input, size_t input_len);
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef DATGPT_ERRNO_COMPAT_H
#define DATGPT_ERRNO_COMPAT_H
#include <errno.h>
/* EKEYREJECTED is a Linux extension. Keep the key-authentication failure
* portable while preserving a useful access-denied error on other hosts. */
#ifndef EKEYREJECTED
#define EKEYREJECTED EACCES
#endif
#endif
+27 -4
View File
@@ -11,7 +11,7 @@ content.key
content.signatures
content.bitfield
content.tree*/
#include "key.h"
#include "keys.h"
#include <stdint.h>
#include <stddef.h>
// test
@@ -21,8 +21,14 @@ content.tree*/
extern "C" {
#endif
int sleep_init(const char *root);
#define SLEEP_HEADER_SIZE 32u
#define SLEEP_MAGIC_BITFIELD 0x05025700u
#define SLEEP_MAGIC_SIGNATURE 0x05025701u
#define SLEEP_MAGIC_TREE 0x05025702u
// TODO MAGIC_BITFIELD, MAGIC_SIG, MAGIC_TREE
#define SLEEP_ALGO_BLAKE2B "BLAKE2b"
@@ -30,7 +36,7 @@ extern "C" {
#define SLEEP_TREE_ENTRY_SIZE 40u
#define SLEEP_SIG_ENTRY_SIZE 64u
#define SLEEP_BITFIELD_ENTRY_SIZE 3328u
#define SLEEP_BITFIELD_ENTRY_SIZE 3584u
enum sleep_hash_type {
SLEEP_HASH_LEAF = 0,
@@ -69,11 +75,12 @@ typedef struct SLEEP_PACKED sleep_sig_entry {
} sleep_sig_entry_t;
// TODO assert
// 3328 bytes: tree[2048] + data[1024] + index[256]
// 3584-byte historical record. The final 256 bytes are opaque for now.
typedef struct SLEEP_PACKED sleep_bitfield_entry {
uint8_t tree[2048];
uint8_t data[1024];
uint8_t tree[2048];
uint8_t index[256];
uint8_t reserved[256];
} sleep_bitfield_entry_t;
// TODO DOTO ODOT assert it
@@ -97,6 +104,22 @@ int sleep_compute_discovery_key(const uint8_t pubkey[32], uint8_t out32[32]);
#endif /* SLEEP_SALT */
// function decs
uint64_t sleep_tree_index(uint64_t depth, uint64_t offset);
uint64_t sleep_tree_depth(uint64_t index);
uint64_t sleep_tree_offset(uint64_t index, uint64_t depth);
uint64_t sleep_tree_parent(uint64_t index);
int sleep_tree_left_child(uint64_t index, uint64_t *out);
int sleep_tree_right_child(uint64_t index, uint64_t *out);
int sleep_tree_sibling(uint64_t index, uint64_t *out);
uint64_t sleep_tree_left_span(uint64_t index);
uint64_t sleep_tree_right_span(uint64_t index);
void sleep_tree_spans(uint64_t index, uint64_t *left, uint64_t *right);
size_t sleep_tree_count(uint64_t index);
size_t sleep_tree_count_leaves(uint64_t index);
size_t sleep_tree_full_roots(uint64_t index, uint64_t *out, size_t capacity);
int sleep_tree_hash_block(const uint8_t *data, size_t len, uint8_t out_hash[32]);
int sleep_tree_hash_parent(const uint8_t left[32], const uint8_t right[32],
uint64_t length, uint8_t out_hash[32]);
#ifdef __cplusplus
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef SLEEP_BITFIELD_H
#define SLEEP_BITFIELD_H
#include <stddef.h>
#include <stdint.h>
#define SLEEP_BITFIELD_DATA_BYTES 1024u
#define SLEEP_BITFIELD_TREE_BYTES 2048u
#define SLEEP_BITFIELD_INDEX_BYTES 256u
#define SLEEP_BITFIELD_RESERVED_BYTES 256u
typedef struct sleep_bitfield {
uint8_t data[SLEEP_BITFIELD_DATA_BYTES];
uint8_t tree[SLEEP_BITFIELD_TREE_BYTES];
uint8_t index[SLEEP_BITFIELD_INDEX_BYTES];
uint8_t reserved[SLEEP_BITFIELD_RESERVED_BYTES];
} sleep_bitfield_t;
void sleep_bitfield_clear(sleep_bitfield_t *field);
int sleep_bitfield_get_data(const sleep_bitfield_t *field, size_t bit);
int sleep_bitfield_get_tree(const sleep_bitfield_t *field, size_t bit);
int sleep_bitfield_set_data(sleep_bitfield_t *field, size_t bit, int present);
int sleep_bitfield_set_tree(sleep_bitfield_t *field, size_t bit, int present);
void sleep_bitfield_reindex(sleep_bitfield_t *field);
size_t sleep_bitfield_next_data(const sleep_bitfield_t *field, size_t start, int present);
int sleep_bitfield_encode(const sleep_bitfield_t *field, uint8_t *out, size_t capacity);
int sleep_bitfield_decode(sleep_bitfield_t *field, const uint8_t *input, size_t length);
#endif
+13 -6
View File
@@ -4,19 +4,26 @@
#include <stddef.h>
#include <stdint.h>
#include "keys.h"
//#include "sleep.h"
#define SLEEP_ROOT_RECORD_BYTES 48u
int sleep_crypto_init(void);
int sleep_stream_xsalsa20_xor(uint8_t *out, const uint8_t *in, size_t length,
const uint8_t nonce[24], const uint8_t key[32],
uint64_t stream_offset);
int sleep_gen_keypair(sleep_keypair_t *kp);
int sleep_save_pubkey(const char *path, const uint8_t pubkey[SLEEP_PUBLIC_KEY_BYTES]);
int sleep_load_pubkey(const char *path, uint8_t pubkey[SLEEP_PUBLIC_KEY_BYTES]);
int sleep_save_pubkey(const char *path, const uint8_t pubkey[SLEEP_PUB_KEY_BYTES]);
int sleep_load_pubkey(const char *path, uint8_t pubkey[SLEEP_PUB_KEY_BYTES]);
int sleep_save_keypair(const char *path, const sleep_keypair_t *keypair);
int sleep_load_keypair(const char *path, sleep_keypair_t *keypair);
int sleep_blake2b(uint8_t out[SLEEP_BLAKE2B_BYTES], const uint8_t *in, size_t inlen);
int sleep_sign(uint8_t sig[SLEEP_BLAKE2B_BYTES], const uint8_t *msg, size_t msglen, const sleep_keypair_t *kp);
int sleep_sign(uint8_t sig[SLEEP_SIGNATURE_BYTES], const uint8_t *msg, size_t msglen, const sleep_keypair_t *kp);
int sleep_verify(const uint8_t sig[SLEEP_SIGNATURE_BYTES], const uint8_t *msg, size_t msglen, const uint8_t pubkey[SLEEP_PUBLIC_KEY_BYTES]);
int sleep_verify(const uint8_t sig[SLEEP_SIGNATURE_BYTES], const uint8_t *msg, size_t msglen, const uint8_t pubkey[SLEEP_PUB_KEY_BYTES]);
int sleep_sign_roots(uint8_t sig[SLEEP_SIGNATURE_BYTES], const uint8_t *roots, size_t nroots, const uint64_t *indices, const uint64_t *lengths, const sleep_keypair_t *kp);
int sleep_verify_roots(const uint8_t sig[SLEEP_SIGNATURE_BYTES], const uint8_t *roots, size_t nroots, const uint64_t *indices, const uint64_t *lengths, const uint8_t pub[SLEEP_PUBLIC_KEY_BYTES]);
int sleep_verify_roots(const uint8_t sig[SLEEP_SIGNATURE_BYTES], const uint8_t *roots, size_t nroots, const uint64_t *indices, const uint64_t *lengths, const uint8_t pub[SLEEP_PUB_KEY_BYTES]);
#endif /* SLEEP_CRYPTO_H */
+43
View File
@@ -0,0 +1,43 @@
#ifndef SLEEP_FEED_H
#define SLEEP_FEED_H
#include <stddef.h>
#include <stdint.h>
#include "keys.h"
typedef struct sleep_feed {
char directory[1024];
char name[64];
uint8_t **blocks;
size_t *lengths;
uint8_t **proofs;
size_t *proof_lengths;
size_t length;
size_t capacity;
sleep_keypair_t keypair;
int writable;
int dirty;
int remote_only;
int persist_remote;
} sleep_feed_t;
int sleep_feed_open(sleep_feed_t *feed, const char *directory, const char *name,
const sleep_keypair_t *keypair);
/* Opens an in-memory, read-only feed replica using only its public key. */
int sleep_feed_open_remote(sleep_feed_t *feed, const char *directory,
const char *name, const uint8_t public_key[32]);
/* Merge verified cached remote blocks and persist subsequent received blocks. */
int sleep_feed_load_remote(sleep_feed_t *feed, const uint8_t public_key[32]);
size_t sleep_feed_length(const sleep_feed_t *feed);
int sleep_feed_read(const sleep_feed_t *feed, size_t index, uint8_t **data, size_t *length);
int sleep_feed_append(sleep_feed_t *feed, const uint8_t *data, size_t length);
/* Keeps already verified remote blocks and proofs in this session's memory. */
int sleep_feed_append_remote(sleep_feed_t *feed, size_t index,
const uint8_t *data, size_t length,
const uint8_t *proof, size_t proof_length);
int sleep_feed_truncate(sleep_feed_t *feed, size_t length);
int sleep_feed_has(const sleep_feed_t *feed, size_t index);
int sleep_feed_byte_offset(const sleep_feed_t *feed, size_t index,
uint64_t *offset);
int sleep_feed_flush(sleep_feed_t *feed);
void sleep_feed_close(sleep_feed_t *feed);
#endif
+43
View File
@@ -0,0 +1,43 @@
#ifndef SLEEP_PROOF_H
#define SLEEP_PROOF_H
#include <stddef.h>
#include <stdint.h>
#include "sleep_feed.h"
#define SLEEP_PROOF_HASH_BYTES 32u
#define SLEEP_PROOF_MAX_NODES 64u
typedef struct sleep_proof_node {
uint64_t index;
uint64_t length;
uint8_t hash[SLEEP_PROOF_HASH_BYTES];
} sleep_proof_node_t;
typedef struct sleep_proof {
uint64_t block;
uint64_t block_length;
uint8_t block_hash[SLEEP_PROOF_HASH_BYTES];
sleep_proof_node_t nodes[SLEEP_PROOF_MAX_NODES];
size_t node_count;
sleep_proof_node_t roots[SLEEP_PROOF_MAX_NODES];
size_t root_count;
uint8_t signature[64];
int has_signature;
} sleep_proof_t;
void sleep_proof_init(sleep_proof_t *proof, uint64_t block);
int sleep_proof_add_node(sleep_proof_t *proof, uint64_t index,
uint64_t length, const uint8_t hash[32]);
int sleep_proof_add_root(sleep_proof_t *proof, uint64_t index,
uint64_t length, const uint8_t hash[32]);
int sleep_proof_create(const sleep_feed_t *feed, uint64_t block,
sleep_proof_t *proof);
int sleep_proof_from_nodes(uint64_t block, const uint8_t *value,
size_t value_len, const sleep_proof_node_t *nodes,
size_t node_count, const uint8_t signature[64],
uint64_t feed_length, sleep_proof_t *proof);
int sleep_proof_encode(const sleep_proof_t *proof, uint8_t *out,
size_t capacity, size_t *written);
int sleep_proof_decode(sleep_proof_t *proof, const uint8_t *input,
size_t input_len);
int sleep_proof_verify(const sleep_proof_t *proof, const uint8_t *block,
size_t block_len, const uint8_t public_key[32]);
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef SLEEP_PROTO_H
#define SLEEP_PROTO_H
#include <stddef.h>
#include <stdint.h>
#define SLEEP_PROTO_KEY_BYTES 32u
typedef struct sleep_metadata_header { char type[32]; uint8_t content[32]; size_t content_len; } sleep_metadata_header_t;
enum sleep_entry_type { SLEEP_ENTRY_FILE=1, SLEEP_ENTRY_DIRECTORY=2, SLEEP_ENTRY_SYMLINK=3, SLEEP_ENTRY_DELETE=4 };
typedef struct sleep_metadata_entry {
char path[1024];
uint32_t type;
uint32_t mode;
uint64_t size;
uint64_t mtime;
uint64_t block_offset;
uint64_t block_count;
char linkname[1024];
} sleep_metadata_entry_t;
size_t sleep_varint_size(uint64_t value);
int sleep_varint_encode(uint64_t value, uint8_t *out, size_t capacity, size_t *written);
int sleep_varint_decode(const uint8_t *input, size_t input_len, uint64_t *value, size_t *consumed);
int sleep_metadata_header_encode(const sleep_metadata_header_t *header, uint8_t *out, size_t capacity, size_t *written);
int sleep_metadata_header_decode(sleep_metadata_header_t *header, const uint8_t *input, size_t input_len);
int sleep_write_metadata_header(const char *path, const uint8_t content_pubkey[32]);
int sleep_metadata_entry_encode(const sleep_metadata_entry_t *entry, uint8_t *out, size_t capacity, size_t *written);
int sleep_metadata_entry_decode(sleep_metadata_entry_t *entry, const uint8_t *input, size_t input_len);
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef SLEEP_REPLICATION_H
#define SLEEP_REPLICATION_H
#include <stddef.h>
#include <stdint.h>
#include "sleep_feed.h"
#include "sleep_bitfield.h"
#include "sleep_proof.h"
#define SLEEP_REPLICATION_QUEUE 128u
typedef struct sleep_replication_request { uint64_t index; uint64_t bytes; int hash; int nodes; } sleep_replication_request_t;
typedef struct sleep_replication {
sleep_feed_t *feed;
uint64_t channel;
uint64_t remote_length;
sleep_bitfield_t remote_bitfield;
sleep_replication_request_t requests[SLEEP_REPLICATION_QUEUE];
size_t request_head, request_count;
int live, uploading, downloading;
} sleep_replication_t;
int sleep_replication_init(sleep_replication_t *replication,
sleep_feed_t *feed, uint64_t channel);
int sleep_replication_have(sleep_replication_t *replication,
uint64_t start, uint64_t length);
int sleep_replication_unhave(sleep_replication_t *replication,
uint64_t start, uint64_t length);
int sleep_replication_want(sleep_replication_t *replication,
uint64_t start, uint64_t length);
int sleep_replication_request(sleep_replication_t *replication,
const sleep_replication_request_t *request);
int sleep_replication_next(sleep_replication_t *replication,
sleep_replication_request_t *request);
int sleep_replication_complete(sleep_replication_t *replication,
uint64_t index);
int sleep_replication_is_requested(const sleep_replication_t *replication,
uint64_t index);
int sleep_replication_unwant(sleep_replication_t *replication,
uint64_t start, uint64_t length);
void sleep_replication_clear_requests(sleep_replication_t *replication);
int sleep_replication_receive(sleep_replication_t *replication,
const uint8_t *block, size_t block_len,
const sleep_proof_t *proof,
const uint8_t feed_public_key[32]);
#endif
+39
View File
@@ -0,0 +1,39 @@
#ifndef SLEEP_UTP_H
#define SLEEP_UTP_H
#include <stddef.h>
#include <stdint.h>
#include "dat_socket.h"
#define SLEEP_UTP_MTU 1200u
#define SLEEP_UTP_WINDOW 64u
enum sleep_utp_state { SLEEP_UTP_CLOSED, SLEEP_UTP_SYN_SENT, SLEEP_UTP_SYN_RECV, SLEEP_UTP_CONNECTED, SLEEP_UTP_FIN_SENT, SLEEP_UTP_RESET };
enum sleep_utp_packet_type { SLEEP_UTP_DATA, SLEEP_UTP_FIN, SLEEP_UTP_STATE, SLEEP_UTP_RESET_PACKET, SLEEP_UTP_SYN };
typedef struct sleep_utp_packet { uint8_t type, version; uint16_t connection_id; uint32_t timestamp, timestamp_diff, window_size; uint16_t sequence, acknowledgement; uint32_t selective_ack; int has_selective_ack; const uint8_t *payload; size_t payload_len; } sleep_utp_packet_t;
typedef struct sleep_utp_slot { uint16_t sequence; uint8_t data[SLEEP_UTP_MTU]; size_t length; uint64_t sent_at; unsigned retries; int used; } sleep_utp_slot_t;
typedef struct sleep_utp {
dat_socket_t socket;
struct sockaddr_storage remote;
socklen_t remote_len;
uint16_t send_id, receive_id, sequence, acknowledgement;
uint32_t receive_window, send_window;
enum sleep_utp_state state;
uint64_t retransmit_at;
unsigned syn_retries;
uint32_t congestion_window, slow_start_threshold;
uint32_t round_trip_time, round_trip_variance;
size_t bytes_in_flight;
sleep_utp_slot_t unacked[SLEEP_UTP_WINDOW];
sleep_utp_slot_t reorder[SLEEP_UTP_WINDOW];
void *context;
void (*on_data)(struct sleep_utp *, const uint8_t *, size_t);
} sleep_utp_t;
int sleep_utp_init(sleep_utp_t *utp, dat_socket_t udp_socket);
int sleep_utp_connect(sleep_utp_t *utp, const struct sockaddr *remote, socklen_t remote_len);
int sleep_utp_accept(sleep_utp_t *utp, const sleep_utp_packet_t *syn, const struct sockaddr *remote, socklen_t remote_len);
int sleep_utp_packet_encode(const sleep_utp_packet_t *packet, uint8_t *out, size_t capacity, size_t *written);
int sleep_utp_packet_decode(sleep_utp_packet_t *packet, const uint8_t *input, size_t input_len);
int sleep_utp_input(sleep_utp_t *utp, const uint8_t *packet, size_t packet_len);
int sleep_utp_send(sleep_utp_t *utp, const uint8_t *data, size_t length);
int sleep_utp_tick(sleep_utp_t *utp, uint64_t now_ms);
int sleep_utp_close(sleep_utp_t *utp);
#endif
+6
View File
@@ -0,0 +1,6 @@
#ifndef SLEEP_VERIFY_H
#define SLEEP_VERIFY_H
int sleep_verify_dat(const char *dat_dir);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef SLEEP_WRITER_H
#define SLEEP_WRITER_H
#include <stddef.h>
#include <stdint.h>
#include "sleep.h"
#ifdef __cplusplus
extern "C" {
#endif
int sleep_write_feed(const char *feed_dir,
const char *feed_name,
const uint8_t *const *blocks,
const size_t *lengths,
size_t nblocks,
const sleep_keypair_t *keypair);
#ifdef __cplusplus
}
#endif
#endif
+80
View File
@@ -0,0 +1,80 @@
#ifndef DATGPT_WIN_COMPAT_H
#define DATGPT_WIN_COMPAT_H
/* Small POSIX spellings used by the shared C sources on native Windows. */
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <process.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#ifndef mkdir
#define mkdir(path, mode) _mkdir(path)
#endif
#ifndef fsync
#define fsync(fd) _commit(fd)
#endif
#ifndef getpid
#define getpid _getpid
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif
#ifndef EKEYREJECTED
#define EKEYREJECTED EACCES
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#endif
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
#ifndef fchmod
#define fchmod(fd, mode) ((void)(fd), (void)(mode), 0)
#endif
#ifndef strcasecmp
#define strcasecmp _stricmp
#endif
#ifndef strncasecmp
#define strncasecmp _strnicmp
#endif
static inline char *dat_win_getenv_compat(const char *name)
{
char *value = getenv(name);
if (!value && name && !strcmp(name, "HOME")) value = getenv("USERPROFILE");
return value;
}
#define getenv dat_win_getenv_compat
static inline int dat_win_lstat(const char *path, struct stat *info)
{
DWORD attributes;
if (stat(path, info)) return -1;
attributes = GetFileAttributesA(path);
if (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_REPARSE_POINT))
info->st_mode = (info->st_mode & ~S_IFMT) | S_IFLNK;
return 0;
}
#ifndef lstat
#define lstat dat_win_lstat
#endif
static inline int dat_win_readlink(const char *path, char *target, size_t capacity)
{ (void)path; (void)target; (void)capacity; errno = ENOTSUP; return -1; }
static inline int dat_win_symlink(const char *target, const char *path)
{ (void)target; (void)path; errno = ENOTSUP; return -1; }
#ifndef readlink
#define readlink dat_win_readlink
#endif
#ifndef symlink
#define symlink dat_win_symlink
#endif
#endif
#endif
+53
View File
@@ -0,0 +1,53 @@
#ifndef DATGPT_WIN_DIRENT_H
#define DATGPT_WIN_DIRENT_H
#ifdef _WIN32
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define NAME_MAX MAX_PATH
typedef struct dirent { char d_name[MAX_PATH]; } struct_dirent_t;
typedef struct dat_win_dir {
HANDLE handle;
WIN32_FIND_DATAA data;
int first;
struct dirent entry;
} DIR;
static DIR *dat_opendir(const char *path)
{
DIR *dir = (DIR *)calloc(1, sizeof(*dir));
char pattern[MAX_PATH * 2];
int n;
if (!dir) return NULL;
n = snprintf(pattern, sizeof(pattern), "%s\\*", path);
if (n < 0 || (size_t)n >= sizeof(pattern)) { free(dir); errno = ENAMETOOLONG; return NULL; }
dir->handle = FindFirstFileA(pattern, &dir->data);
if (dir->handle == INVALID_HANDLE_VALUE) { free(dir); errno = ENOENT; return NULL; }
dir->first = 1;
return dir;
}
static struct dirent *dat_readdir(DIR *dir)
{
if (!dir) return NULL;
if (dir->first) dir->first = 0;
else if (!FindNextFileA(dir->handle, &dir->data)) return NULL;
strncpy(dir->entry.d_name, dir->data.cFileName, sizeof(dir->entry.d_name) - 1);
dir->entry.d_name[sizeof(dir->entry.d_name) - 1] = 0;
return &dir->entry;
}
static int dat_closedir(DIR *dir)
{
int rc;
if (!dir) { errno = EINVAL; return -1; }
rc = FindClose(dir->handle) ? 0 : -1;
free(dir);
return rc;
}
#define opendir dat_opendir
#define readdir dat_readdir
#define closedir dat_closedir
#else
#include <dirent.h>
#endif
#endif
+24
View File
@@ -0,0 +1,24 @@
#ifndef DATGPT_WIN_FNMATCH_H
#define DATGPT_WIN_FNMATCH_H
#ifdef _WIN32
static int dat_win_fnmatch(const char *pattern, const char *text)
{
while (*pattern) {
if (*pattern == '*') {
while (*pattern == '*') pattern++;
if (!*pattern) return 0;
do { if (dat_win_fnmatch(pattern, text) == 0) return 0; } while (*text++);
return 1;
}
if (!*text) return 1;
if (*pattern == '?') { pattern++; text++; continue; }
if (*pattern != *text) return 1;
pattern++; text++;
}
return *text ? 1 : 0;
}
#define fnmatch(pattern, text, flags) ((void)(flags), dat_win_fnmatch((pattern), (text)))
#else
#include <fnmatch.h>
#endif
#endif