1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
* net_transport.h — C ABI for the Net transport surface:
* blob transfer + directory transfer over the fairscheduler stream
* transport (Transport SDK plan, T-C).
*
* One of eleven headers, all resolving against a single shared library.
* These symbols are exported by the same `libnet` cdylib as the rest of
* the C ABI; this header only declares the transport slice. The transfer
* engine moves
* content-addressed bytes (and whole directory trees) between peers
* over reliable, fair-scheduled streams — distinct from RedEX
* replication (a push primitive) and nRPC (request/reply).
*
* # Build
* cargo build --release -p net-ffi
* Artifacts (in target/release): libnet.so (Linux),
* libnet.dylib (macOS), net.dll + net.dll.lib (Windows).
*
* # Link
* gcc -o transport transport.c -L target/release \
* -lnet -lpthread -ldl -lm
*
* Link `-lnet` and nothing else; there is no second library to add.
*
* # Handle model
* Transfer is node-driven, so the fetch/dir functions take a
* `net_meshnode_t*` (from net_mesh_new, see net.go.h), and the
* store/serve functions take a `net_mesh_blob_adapter_t*` (from
* net_mesh_blob_adapter_new). No transport-specific handle type is
* introduced. Both handles remain owned by their creators and are
* freed by their own `_free` functions; this surface only borrows
* them for the duration of a call.
*
* A node MUST install the transfer engine via
* net_serve_blob_transfer() before it can serve chunks to peers OR
* issue its own fetches. An un-installed node returns
* NET_ERR_TRANSFER_ENGINE_NOT_INSTALLED.
*
* # Error model
* Functions return 0 (NET_TRANSPORT_OK) on success or a negative
* NET_ERR_TRANSFER_* / NET_ERR_DIR_* code. The codes occupy a fresh
* band (-200..) disjoint from the base (net.h), blob (-110..-120),
* and NAT (-130..-137) ranges.
*
* # Memory
* Byte buffers returned via (out_bytes, out_len) — net_fetch_blob,
* net_fetch_blob_discovered, net_store_dir — are owned by the caller
* and MUST be freed with net_transport_free_buffer(ptr, len). The
* JSON string from net_dir_manifest_read is freed with
* net_free_string (see net.go.h). A successful call with no bytes
* yields (NULL, 0), which is safe to pass to the free function.
*
* # Threading
* Do NOT call any transport function from a thread that already
* holds a tokio runtime context (the synchronous functions block on
* an internal runtime; a runtime-in-runtime aborts). The common
* C / Go / Python caller has no Rust runtime, so this is unreachable
* for them. Panics crossing the boundary are caught and returned as
* NET_ERR_TRANSFER_PANIC.
*/
extern "C" NET_MESHNODE_T_DEFINED
typedef struct net_meshnode_s net_meshnode_t;
typedef struct net_mesh_blob_adapter_s net_mesh_blob_adapter_t;
/*
* Install the blob-transfer engine on `node` over `adapter`. Required
* before the node can serve chunks to peers OR issue its own fetches.
* Idempotent (re-installing replaces the engine). Returns
* NET_TRANSPORT_OK, or NET_ERR_TRANSFER_NULL_POINTER /
* NET_ERR_TRANSFER_SHUTTING_DOWN.
*/
int ;
/*
* Fetch the blob addressed by the 32-byte BLAKE3 `hash` from the known
* holder `holder_id`. On success writes a freshly-allocated buffer to
* (*out_bytes, *out_len); free with net_transport_free_buffer. `hash`
* must point to at least 32 readable bytes.
*/
int ;
/*
* Like net_fetch_blob, but discovers the holder among connected peers.
* Returns NET_ERR_TRANSFER_ALL_PEERS_FAILED if no connected peer has
* the content.
*/
int ;
/*
* Store the local directory tree at `root_path` as content-addressed
* blobs in `adapter`, writing the encoded directory-manifest BlobRef to
* (*out_manifest_ref, *out_len). That buffer is the opaque token a
* receiver passes to net_fetch_dir / net_dir_manifest_read; free it
* with net_transport_free_buffer. `root_path` is a UTF-8, NUL-terminated
* filesystem path.
*/
int ;
/*
* Fetch the directory whose encoded manifest BlobRef is
* (manifest_ref, manifest_ref_len) from `source_id` and reconstruct it
* under `dest_path` (created if absent). Writes the number of files
* written to *out_files and total bytes to *out_bytes; either out-param
* may be NULL to ignore. Both are set to 0 on entry, so on any non-OK
* return they read 0 rather than an indeterminate value. Manifest paths
* are validated to stay within `dest_path`.
*/
int ;
/*
* Fetch + decode the directory manifest (manifest_ref, manifest_ref_len)
* from `source_id` WITHOUT reconstructing the tree, writing it as a JSON
* string to (*out_json, *out_len) for introspection (entry paths, kinds,
* modes, per-file blob refs). Free the string with net_free_string.
* (*out_json, *out_len) is set to (NULL, 0) on entry, so on any non-OK
* return it reads (NULL, 0) rather than an indeterminate value.
*/
int ;
/*
* Free a byte buffer returned by net_fetch_blob / net_fetch_blob_discovered
* / net_store_dir. NULL or zero-length is a no-op. `len` MUST be the
* length the producing call wrote to *out_len (the deallocation layout
* is length-sensitive). Do not call twice on the same pointer.
*/
void ;
}
/* NET_TRANSPORT_H */