fleetmesh-node 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fleetmesh_node-0.2.0.dist-info/METADATA +57 -0
- fleetmesh_node-0.2.0.dist-info/RECORD +338 -0
- fleetmesh_node-0.2.0.dist-info/WHEEL +5 -0
- fleetmesh_node-0.2.0.dist-info/entry_points.txt +2 -0
- fleetmesh_node-0.2.0.dist-info/licenses/LICENSE +121 -0
- fleetmesh_node-0.2.0.dist-info/top_level.txt +2 -0
- node/RELEASE +1 -0
- node/__init__.py +35 -0
- node/app/__init__.py +49 -0
- node/app/commands.py +265 -0
- node/app/config.py +131 -0
- node/app/control.py +670 -0
- node/app/core.py +867 -0
- node/app/plugins.py +76 -0
- node/app/router.py +83 -0
- node/app/socket.py +431 -0
- node/app/systemd.py +36 -0
- node/app/views.py +204 -0
- node/channels/__init__.py +378 -0
- node/channels/bus.py +331 -0
- node/channels/journal.py +46 -0
- node/commands/__init__.py +140 -0
- node/commands/adapter.py +210 -0
- node/commands/base.py +278 -0
- node/commands/cluster_cmds.py +183 -0
- node/commands/compute_cmds.py +401 -0
- node/commands/core.py +474 -0
- node/commands/gossip_cmds.py +106 -0
- node/commands/nsite_cmds.py +141 -0
- node/commands/peering.py +402 -0
- node/commands/plugin_cmds.py +135 -0
- node/commands/sidecar_cmds.py +120 -0
- node/commands/sync.py +388 -0
- node/commands/transport_cmds.py +451 -0
- node/commands/video_cmds.py +99 -0
- node/compartment/__init__.py +124 -0
- node/compartment/base.py +868 -0
- node/compartment/command.py +458 -0
- node/compartment/context.py +163 -0
- node/compartment/every.py +108 -0
- node/compartment/handler.py +131 -0
- node/compartment/lifecycle.py +460 -0
- node/compartment/lint.py +388 -0
- node/compartment/need.py +158 -0
- node/compartment/problem.py +521 -0
- node/compartment/refusals.py +120 -0
- node/compartment/registry.py +790 -0
- node/compartment/schema.py +290 -0
- node/compartment/sidecar.py +499 -0
- node/compartment/stores.py +662 -0
- node/compartment/wire.py +225 -0
- node/compartment/worker.py +61 -0
- node/config/__init__.py +43 -0
- node/config/base.py +116 -0
- node/config/change.py +441 -0
- node/config/changestore.py +201 -0
- node/config/compartments.py +1144 -0
- node/config/node.py +318 -0
- node/config/parameter.py +563 -0
- node/config/protocols.py +274 -0
- node/config/records.py +171 -0
- node/examples/__init__.py +1 -0
- node/examples/demo.py +226 -0
- node/examples/follower.py +46 -0
- node/interfaces.py +235 -0
- node/keystore/__init__.py +27 -0
- node/keystore/core.py +103 -0
- node/keystore/enclave.py +688 -0
- node/meshnode.py +111 -0
- node/metrics/__init__.py +396 -0
- node/metrics/adapters.py +102 -0
- node/metrics/face.py +110 -0
- node/planes/__init__.py +21 -0
- node/planes/identity/__init__.py +20 -0
- node/planes/identity/announce/__init__.py +9 -0
- node/planes/identity/announce/compartment.py +447 -0
- node/planes/identity/announce/types.py +26 -0
- node/planes/identity/discovery/__init__.py +9 -0
- node/planes/identity/discovery/compartment.py +522 -0
- node/planes/identity/discovery/types.py +13 -0
- node/planes/identity/linked/__init__.py +1 -0
- node/planes/identity/linked/compartment.py +270 -0
- node/planes/identity/linked/types.py +25 -0
- node/planes/identity/presence/__init__.py +7 -0
- node/planes/identity/presence/compartment.py +409 -0
- node/planes/identity/presence/types.py +14 -0
- node/planes/operations/__init__.py +13 -0
- node/planes/operations/scheduler/__init__.py +9 -0
- node/planes/operations/scheduler/compartment.py +353 -0
- node/planes/operations/scheduler/types.py +21 -0
- node/planes/operations/updates/__init__.py +17 -0
- node/planes/operations/updates/core.py +310 -0
- node/planes/operations/updates/store.py +79 -0
- node/planes/operations/updates/types.py +20 -0
- node/planes/peering/__init__.py +28 -0
- node/planes/peering/budget/__init__.py +43 -0
- node/planes/peering/budget/chain.py +43 -0
- node/planes/peering/budget/core.py +537 -0
- node/planes/peering/budget/evaluation.py +80 -0
- node/planes/peering/budget/meter.py +100 -0
- node/planes/peering/budget/receipts.py +439 -0
- node/planes/peering/budget/shape.py +101 -0
- node/planes/peering/budget/tick.py +110 -0
- node/planes/peering/budget/types.py +67 -0
- node/planes/peering/budget/windows.py +346 -0
- node/planes/peering/capacity/__init__.py +7 -0
- node/planes/peering/capacity/compartment.py +342 -0
- node/planes/peering/capacity/types.py +24 -0
- node/planes/peering/peering/__init__.py +25 -0
- node/planes/peering/peering/core.py +464 -0
- node/planes/peering/peering/envelope.py +142 -0
- node/planes/peering/peering/handshake.py +198 -0
- node/planes/peering/peering/shape.py +80 -0
- node/planes/peering/peering/types.py +39 -0
- node/planes/peering/reporter/__init__.py +42 -0
- node/planes/peering/reporter/constants.py +29 -0
- node/planes/peering/reporter/core.py +299 -0
- node/planes/peering/reporter/finding.py +74 -0
- node/planes/peering/reporter/findings.py +171 -0
- node/planes/peering/reporter/publish.py +285 -0
- node/planes/peering/reporter/reading.py +193 -0
- node/planes/peering/reporter/shape.py +86 -0
- node/planes/peering/reporter/types.py +50 -0
- node/planes/peering/strain/__init__.py +9 -0
- node/planes/peering/strain/compartment.py +204 -0
- node/planes/peering/strain/types.py +21 -0
- node/planes/peering/trust/__init__.py +9 -0
- node/planes/peering/trust/compartment.py +239 -0
- node/planes/peering/trust/types.py +30 -0
- node/planes/services/__init__.py +33 -0
- node/planes/services/compute/__init__.py +160 -0
- node/planes/services/compute/common.py +134 -0
- node/planes/services/compute/compartment.py +681 -0
- node/planes/services/compute/executors/__init__.py +121 -0
- node/planes/services/compute/executors/agent.py +840 -0
- node/planes/services/compute/executors/bacalhau.py +605 -0
- node/planes/services/compute/executors/base.py +127 -0
- node/planes/services/compute/executors/harness.py +439 -0
- node/planes/services/compute/executors/mcp.py +454 -0
- node/planes/services/compute/executors/media.py +898 -0
- node/planes/services/compute/executors/nondet.py +283 -0
- node/planes/services/compute/executors/providers.py +499 -0
- node/planes/services/compute/executors/registry.py +140 -0
- node/planes/services/compute/executors/wasm.py +244 -0
- node/planes/services/compute/executors/zk.py +604 -0
- node/planes/services/compute/jobs.py +227 -0
- node/planes/services/compute/load.py +180 -0
- node/planes/services/compute/market.py +433 -0
- node/planes/services/compute/sandbox.py +282 -0
- node/planes/services/compute/types.py +84 -0
- node/planes/services/compute_wire/__init__.py +58 -0
- node/planes/services/compute_wire/compartment.py +256 -0
- node/planes/services/compute_wire/messages.py +320 -0
- node/planes/services/compute_wire/sealing.py +147 -0
- node/planes/services/compute_wire/session.py +572 -0
- node/planes/services/compute_wire/types.py +49 -0
- node/planes/services/compute_wire/verify.py +331 -0
- node/planes/services/dvm/__init__.py +24 -0
- node/planes/services/dvm/gateway.py +526 -0
- node/planes/services/dvm/protocol.py +35 -0
- node/planes/services/dvm/translate.py +15 -0
- node/planes/services/dvm/types.py +25 -0
- node/planes/services/gateway/__init__.py +40 -0
- node/planes/services/gateway/settle.py +279 -0
- node/planes/services/gateway/translate.py +644 -0
- node/planes/services/gossip/__init__.py +22 -0
- node/planes/services/gossip/core.py +929 -0
- node/planes/services/gossip/envelope.py +154 -0
- node/planes/services/gossip/mesh.py +127 -0
- node/planes/services/gossip/types.py +50 -0
- node/planes/services/nsite/__init__.py +7 -0
- node/planes/services/nsite/client.py +62 -0
- node/planes/services/nsite/compartment.py +752 -0
- node/planes/services/nsite/types.py +44 -0
- node/planes/services/paidfetch/__init__.py +7 -0
- node/planes/services/paidfetch/compartment.py +862 -0
- node/planes/services/paidfetch/types.py +99 -0
- node/planes/services/settle/__init__.py +27 -0
- node/planes/services/settle/compartment.py +384 -0
- node/planes/services/settle/engine.py +456 -0
- node/planes/services/settle/gateways.py +541 -0
- node/planes/services/settle/payment.py +512 -0
- node/planes/services/settle/store.py +74 -0
- node/planes/services/settle/types.py +58 -0
- node/planes/services/sidecars/__init__.py +8 -0
- node/planes/services/sidecars/compartment.py +461 -0
- node/planes/services/sidecars/manifest.py +304 -0
- node/planes/services/sidecars/manifests/10-grasp.json +37 -0
- node/planes/services/sidecars/manifests/20-ncontainer.json +31 -0
- node/planes/services/sidecars/manifests/30-magpie.json +28 -0
- node/planes/services/sidecars/types.py +43 -0
- node/planes/services/video/__init__.py +106 -0
- node/planes/services/video/barter.py +407 -0
- node/planes/services/video/cli.py +158 -0
- node/planes/services/video/compartment.py +932 -0
- node/planes/services/video/ingest.py +524 -0
- node/planes/services/video/ledger.py +705 -0
- node/planes/services/video/packager.py +847 -0
- node/planes/services/video/player.py +456 -0
- node/planes/services/video/timed_segments.py +124 -0
- node/planes/services/video/transit.py +478 -0
- node/planes/store/__init__.py +24 -0
- node/planes/store/blob_replication/__init__.py +7 -0
- node/planes/store/blob_replication/compartment.py +496 -0
- node/planes/store/blob_replication/types.py +35 -0
- node/planes/store/blob_wire/__init__.py +48 -0
- node/planes/store/blob_wire/client.py +57 -0
- node/planes/store/blob_wire/core.py +359 -0
- node/planes/store/blob_wire/intake.py +74 -0
- node/planes/store/blob_wire/messages.py +85 -0
- node/planes/store/projected/__init__.py +7 -0
- node/planes/store/projected/compartment.py +258 -0
- node/planes/store/projected/types.py +29 -0
- node/planes/store/retention/__init__.py +7 -0
- node/planes/store/retention/compartment.py +214 -0
- node/planes/store/retention/types.py +12 -0
- node/planes/store/sync/__init__.py +35 -0
- node/planes/store/sync/core.py +311 -0
- node/planes/store/sync/envelope.py +106 -0
- node/planes/store/sync/handover.py +206 -0
- node/planes/store/sync/initiator.py +128 -0
- node/planes/store/sync/responder.py +114 -0
- node/planes/store/sync/rules.py +179 -0
- node/planes/store/sync/shape.py +80 -0
- node/planes/store/sync/types.py +51 -0
- node/planes/transport/__init__.py +23 -0
- node/planes/transport/bridge/__init__.py +13 -0
- node/planes/transport/bridge/compartment.py +785 -0
- node/planes/transport/bridge/ratelimit.py +44 -0
- node/planes/transport/bridge/types.py +43 -0
- node/planes/transport/lan/__init__.py +9 -0
- node/planes/transport/lan/compartment.py +446 -0
- node/planes/transport/lan/types.py +25 -0
- node/planes/transport/link/__init__.py +7 -0
- node/planes/transport/link/compartment.py +257 -0
- node/planes/transport/link/types.py +27 -0
- node/planes/transport/mediation/__init__.py +45 -0
- node/planes/transport/mediation/compartment.py +238 -0
- node/planes/transport/mediation/leaf.py +107 -0
- node/planes/transport/mediation/messages.py +302 -0
- node/planes/transport/mediation/service.py +233 -0
- node/planes/transport/mediation/store.py +37 -0
- node/planes/transport/mediation/types.py +20 -0
- node/planes/transport/p2p/__init__.py +7 -0
- node/planes/transport/p2p/compartment.py +349 -0
- node/planes/transport/p2p/types.py +22 -0
- node/protocols/__init__.py +277 -0
- node/protocols/activitypub/__init__.py +56 -0
- node/protocols/activitypub/actor.py +230 -0
- node/protocols/activitypub/federation.py +490 -0
- node/protocols/activitypub/media.py +145 -0
- node/protocols/activitypub/models.py +286 -0
- node/protocols/activitypub/package.py +271 -0
- node/protocols/activitypub/store.py +564 -0
- node/protocols/arcade/__init__.py +26 -0
- node/protocols/atproto/__init__.py +13 -0
- node/protocols/atproto/firehose.py +126 -0
- node/protocols/atproto/metering.py +165 -0
- node/protocols/atproto/package.py +155 -0
- node/protocols/atproto/repo.py +250 -0
- node/protocols/atproto/xrpc.py +285 -0
- node/protocols/base.py +109 -0
- node/protocols/circles/__init__.py +29 -0
- node/protocols/dm/__init__.py +50 -0
- node/protocols/grasp/__init__.py +22 -0
- node/protocols/isotime.py +15 -0
- node/protocols/nostr/__init__.py +51 -0
- node/protocols/nostr/blobstore.py +383 -0
- node/protocols/nostr/blossom.py +627 -0
- node/protocols/nostr/client.py +377 -0
- node/protocols/nostr/descriptor.py +211 -0
- node/protocols/nostr/eventstore.py +304 -0
- node/protocols/nostr/package.py +182 -0
- node/protocols/nostr/peers.py +109 -0
- node/protocols/nostr/relayserver.py +656 -0
- node/protocols/p2panda/__init__.py +22 -0
- node/protocols/p2panda/identity.py +19 -0
- node/protocols/p2panda/package.py +236 -0
- node/protocols/p2panda/rung.py +152 -0
- node/protocols/p2panda/store.py +273 -0
- node/protocols/rhio/__init__.py +33 -0
- node/protocols/rhio/package.py +275 -0
- node/protocols/rhio/rung.py +136 -0
- node/protocols/rhio/store.py +1423 -0
- node/protocols/ssb/muxrpc.py +256 -0
- node/protocols/ssb/package.py +267 -0
- node/protocols/textile/__init__.py +111 -0
- node/protocols/textile/transducers.py +259 -0
- node/release.py +119 -0
- node/storage/__init__.py +88 -0
- node/storage/accounts.py +305 -0
- node/storage/adapter.py +161 -0
- node/storage/base.py +385 -0
- node/storage/dialect.py +209 -0
- node/storage/grants.py +317 -0
- node/storage/locator.py +150 -0
- node/storage/postgres.py +294 -0
- node/storage/projected.py +953 -0
- node/storage/sharding.py +448 -0
- node/storage/standing.py +568 -0
- node/testnet/__init__.py +9 -0
- node/testnet/cluster.py +731 -0
- node/testnet/fips_daemon.py +230 -0
- node/transport/__init__.py +94 -0
- node/transport/const.py +110 -0
- node/transport/didcomm_inbound.py +251 -0
- node/transport/dnstxt.py +169 -0
- node/transport/fips_rung/__init__.py +67 -0
- node/transport/fips_rung/core.py +666 -0
- node/transport/fips_rung/listener.py +96 -0
- node/transport/fips_rung/types.py +12 -0
- node/transport/host.py +334 -0
- node/transport/iroh_rung/__init__.py +29 -0
- node/transport/iroh_rung/core.py +477 -0
- node/transport/iroh_rung/quic.py +942 -0
- node/transport/iroh_rung/types.py +22 -0
- node/transport/ladder.py +145 -0
- node/transport/lineproto.py +49 -0
- node/transport/mdns.py +303 -0
- node/transport/netfetch.py +283 -0
- node/transport/relay_rung/__init__.py +23 -0
- node/transport/relay_rung/cooldown.py +87 -0
- node/transport/relay_rung/core.py +138 -0
- node/transport/relay_rung/inbound.py +161 -0
- node/transport/relay_rung/ledger.py +104 -0
- node/transport/relay_rung/listen.py +121 -0
- node/transport/relay_rung/outbound.py +181 -0
- node/transport/relay_rung/shape.py +71 -0
- node/transport/relay_rung/types.py +58 -0
- node/transport/relay_rung/wire.py +63 -0
- node/transport/router.py +761 -0
- node/transport/rung.py +276 -0
- node/transport/ssb_rung.py +166 -0
- node/transport/ws.py +502 -0
- sidecar/fleetmesh_announce.py +338 -0
- sidecar/fleetmesh_p2p.py +373 -0
- sidecar/fleetmesh_rhio.py +352 -0
- sidecar/fleetmesh_ssb.py +603 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Secure Scuttlebutt (SSB) MuxRPC Protocol Framing and Method Dispatcher (SSB-MuxRPC).
|
|
2
|
+
|
|
3
|
+
Standard library only. Manages:
|
|
4
|
+
- 9-byte packet framing (flags, body length, request ID) for SSB-MuxRPC.
|
|
5
|
+
- Supported payload encodings: binary (00), UTF-8 text (01), JSON (10).
|
|
6
|
+
- Procedure calls: async, sync, source, duplex, sink.
|
|
7
|
+
- Feed history streaming (createHistoryStream) with stream termination.
|
|
8
|
+
- Error propagation and stream completion flags.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import struct
|
|
14
|
+
from typing import Any, Callable, Mapping, Optional, Sequence, Union
|
|
15
|
+
|
|
16
|
+
from fleetmesh_core.conformance.errors import FleetmeshError
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
'MuxRPCError',
|
|
20
|
+
'PS_TYPE_BUFFER',
|
|
21
|
+
'PS_TYPE_TEXT',
|
|
22
|
+
'PS_TYPE_JSON',
|
|
23
|
+
'FLAG_STREAM',
|
|
24
|
+
'FLAG_END_ERR',
|
|
25
|
+
'MuxRPCMessage',
|
|
26
|
+
'build_request',
|
|
27
|
+
'build_response',
|
|
28
|
+
'build_error_response',
|
|
29
|
+
'build_stream_end',
|
|
30
|
+
'MuxRPCRouter',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
PS_TYPE_BUFFER = 0
|
|
34
|
+
PS_TYPE_TEXT = 1
|
|
35
|
+
PS_TYPE_JSON = 2
|
|
36
|
+
|
|
37
|
+
FLAG_STREAM = 0x08
|
|
38
|
+
FLAG_END_ERR = 0x04
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class MuxRPCError(FleetmeshError):
|
|
42
|
+
"""Base error for MuxRPC operations."""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
MAX_MUXRPC_BODY_LEN = 16 * 1024 * 1024 # 16 MB
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class MuxRPCMessage:
|
|
49
|
+
"""A single MuxRPC packet with a 9-byte binary header and body."""
|
|
50
|
+
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
req: int,
|
|
54
|
+
body: Union[bytes, str, Mapping[str, Any], list[Any], bool, int, float, None],
|
|
55
|
+
body_type: int = PS_TYPE_JSON,
|
|
56
|
+
is_stream: bool = False,
|
|
57
|
+
is_end_err: bool = False,
|
|
58
|
+
):
|
|
59
|
+
self.req = req
|
|
60
|
+
self.body = body
|
|
61
|
+
self.body_type = body_type
|
|
62
|
+
self.is_stream = is_stream
|
|
63
|
+
self.is_end_err = is_end_err
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def flags(self) -> int:
|
|
67
|
+
f = self.body_type & 0x03
|
|
68
|
+
if self.is_stream:
|
|
69
|
+
f |= FLAG_STREAM
|
|
70
|
+
if self.is_end_err:
|
|
71
|
+
f |= FLAG_END_ERR
|
|
72
|
+
return f
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def raw_body_bytes(self) -> bytes:
|
|
76
|
+
if self.body_type == PS_TYPE_BUFFER:
|
|
77
|
+
return bytes(self.body) if isinstance(self.body, (bytes, bytearray)) else b""
|
|
78
|
+
elif self.body_type == PS_TYPE_TEXT:
|
|
79
|
+
return str(self.body).encode('utf-8')
|
|
80
|
+
elif self.body_type == PS_TYPE_JSON:
|
|
81
|
+
return json.dumps(self.body, separators=(',', ':')).encode('utf-8')
|
|
82
|
+
return b""
|
|
83
|
+
|
|
84
|
+
def encode(self) -> bytes:
|
|
85
|
+
"""Encode to 9-byte header followed by body bytes."""
|
|
86
|
+
body_bytes = self.raw_body_bytes
|
|
87
|
+
header = struct.pack('>BIi', self.flags, len(body_bytes), self.req)
|
|
88
|
+
return header + body_bytes
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def from_bytes(cls, data: bytes) -> tuple[Optional[MuxRPCMessage], int]:
|
|
92
|
+
"""Decode message from wire bytes.
|
|
93
|
+
|
|
94
|
+
Returns (message, bytes_consumed) if a full message is available.
|
|
95
|
+
Returns (None, 0) if more bytes are needed.
|
|
96
|
+
"""
|
|
97
|
+
if len(data) < 9:
|
|
98
|
+
return None, 0
|
|
99
|
+
|
|
100
|
+
flags, length, req = struct.unpack('>BIi', data[:9])
|
|
101
|
+
if length > MAX_MUXRPC_BODY_LEN:
|
|
102
|
+
raise MuxRPCError(f"MuxRPC packet length exceeds maximum ({length} > {MAX_MUXRPC_BODY_LEN})")
|
|
103
|
+
|
|
104
|
+
total_len = 9 + length
|
|
105
|
+
if len(data) < total_len:
|
|
106
|
+
return None, 0
|
|
107
|
+
|
|
108
|
+
body_raw = data[9:total_len]
|
|
109
|
+
body_type = flags & 0x03
|
|
110
|
+
is_stream = bool(flags & FLAG_STREAM)
|
|
111
|
+
is_end_err = bool(flags & FLAG_END_ERR)
|
|
112
|
+
|
|
113
|
+
body: Any
|
|
114
|
+
if body_type == PS_TYPE_BUFFER:
|
|
115
|
+
body = body_raw
|
|
116
|
+
elif body_type == PS_TYPE_TEXT:
|
|
117
|
+
body = body_raw.decode('utf-8', errors='replace')
|
|
118
|
+
elif body_type == PS_TYPE_JSON:
|
|
119
|
+
if not body_raw:
|
|
120
|
+
body = None
|
|
121
|
+
else:
|
|
122
|
+
try:
|
|
123
|
+
body = json.loads(body_raw.decode('utf-8'))
|
|
124
|
+
except Exception as e:
|
|
125
|
+
raise MuxRPCError(f"invalid JSON payload in MuxRPC packet: {e}") from e
|
|
126
|
+
else:
|
|
127
|
+
body = body_raw
|
|
128
|
+
|
|
129
|
+
msg = cls(
|
|
130
|
+
req=req,
|
|
131
|
+
body=body,
|
|
132
|
+
body_type=body_type,
|
|
133
|
+
is_stream=is_stream,
|
|
134
|
+
is_end_err=is_end_err,
|
|
135
|
+
)
|
|
136
|
+
return msg, total_len
|
|
137
|
+
|
|
138
|
+
def __repr__(self) -> str:
|
|
139
|
+
return (
|
|
140
|
+
f"<MuxRPCMessage req={self.req} type={self.body_type} "
|
|
141
|
+
f"stream={self.is_stream} end_err={self.is_end_err} body={self.body!r}>"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def build_request(
|
|
146
|
+
req_id: int,
|
|
147
|
+
name: Sequence[str],
|
|
148
|
+
args: Sequence[Any],
|
|
149
|
+
rpc_type: str = "async",
|
|
150
|
+
) -> MuxRPCMessage:
|
|
151
|
+
"""Build an outbound MuxRPC request message."""
|
|
152
|
+
body = {
|
|
153
|
+
"name": list(name),
|
|
154
|
+
"args": list(args),
|
|
155
|
+
"type": rpc_type,
|
|
156
|
+
}
|
|
157
|
+
is_stream = rpc_type in ("source", "duplex", "sink")
|
|
158
|
+
return MuxRPCMessage(
|
|
159
|
+
req=req_id,
|
|
160
|
+
body=body,
|
|
161
|
+
body_type=PS_TYPE_JSON,
|
|
162
|
+
is_stream=is_stream,
|
|
163
|
+
is_end_err=False,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def build_response(
|
|
168
|
+
req_id: int,
|
|
169
|
+
payload: Any,
|
|
170
|
+
is_stream: bool = False,
|
|
171
|
+
is_end_err: bool = False,
|
|
172
|
+
body_type: int = PS_TYPE_JSON,
|
|
173
|
+
) -> MuxRPCMessage:
|
|
174
|
+
"""Build a standard response message (response req is negative)."""
|
|
175
|
+
return MuxRPCMessage(
|
|
176
|
+
req=-abs(req_id),
|
|
177
|
+
body=payload,
|
|
178
|
+
body_type=body_type,
|
|
179
|
+
is_stream=is_stream,
|
|
180
|
+
is_end_err=is_end_err,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def build_error_response(req_id: int, message: str, is_stream: bool = False) -> MuxRPCMessage:
|
|
185
|
+
"""Build an error response packet with end_err=True."""
|
|
186
|
+
return MuxRPCMessage(
|
|
187
|
+
req=-abs(req_id),
|
|
188
|
+
body={"name": "Error", "message": message},
|
|
189
|
+
body_type=PS_TYPE_JSON,
|
|
190
|
+
is_stream=is_stream,
|
|
191
|
+
is_end_err=True,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def build_stream_end(req_id: int) -> MuxRPCMessage:
|
|
196
|
+
"""Build an end-of-stream indicator (JSON true with stream and end_err set)."""
|
|
197
|
+
return MuxRPCMessage(
|
|
198
|
+
req=-abs(req_id),
|
|
199
|
+
body=True,
|
|
200
|
+
body_type=PS_TYPE_JSON,
|
|
201
|
+
is_stream=True,
|
|
202
|
+
is_end_err=True,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class MuxRPCRouter:
|
|
207
|
+
"""Dispatches MuxRPC procedure calls to registered handlers."""
|
|
208
|
+
|
|
209
|
+
def __init__(self, local_feed_id: str = "@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=.ed25519"):
|
|
210
|
+
self.local_feed_id = local_feed_id
|
|
211
|
+
self._handlers: dict[str, Callable[[int, list[Any], str], list[MuxRPCMessage]]] = {}
|
|
212
|
+
self._register_default_handlers()
|
|
213
|
+
|
|
214
|
+
def register(
|
|
215
|
+
self,
|
|
216
|
+
name: str,
|
|
217
|
+
handler: Callable[[int, list[Any], str], list[MuxRPCMessage]],
|
|
218
|
+
) -> None:
|
|
219
|
+
"""Register a procedure handler."""
|
|
220
|
+
self._handlers[name] = handler
|
|
221
|
+
|
|
222
|
+
def _register_default_handlers(self) -> None:
|
|
223
|
+
# whoami
|
|
224
|
+
def _handle_whoami(req_id: int, args: list[Any], rpc_type: str) -> list[MuxRPCMessage]:
|
|
225
|
+
return [build_response(req_id, {"id": self.local_feed_id})]
|
|
226
|
+
|
|
227
|
+
self.register("whoami", _handle_whoami)
|
|
228
|
+
|
|
229
|
+
# blobs.has
|
|
230
|
+
def _handle_blobs_has(req_id: int, args: list[Any], rpc_type: str) -> list[MuxRPCMessage]:
|
|
231
|
+
# Expects list of blob hashes, returns list of booleans
|
|
232
|
+
return [build_response(req_id, [False] * len(args))]
|
|
233
|
+
|
|
234
|
+
self.register("blobs.has", _handle_blobs_has)
|
|
235
|
+
|
|
236
|
+
def handle_request(self, msg: MuxRPCMessage) -> list[MuxRPCMessage]:
|
|
237
|
+
"""Dispatch an incoming MuxRPC request and return zero or more response messages."""
|
|
238
|
+
if not isinstance(msg.body, dict):
|
|
239
|
+
return [build_error_response(msg.req, "Malformed RPC request: expected JSON object")]
|
|
240
|
+
|
|
241
|
+
name_list = msg.body.get("name")
|
|
242
|
+
if not name_list or not isinstance(name_list, list):
|
|
243
|
+
return [build_error_response(msg.req, "Malformed RPC request: missing or invalid 'name'")]
|
|
244
|
+
|
|
245
|
+
method_name = ".".join(name_list)
|
|
246
|
+
args = msg.body.get("args", [])
|
|
247
|
+
rpc_type = msg.body.get("type", "async")
|
|
248
|
+
|
|
249
|
+
handler = self._handlers.get(method_name)
|
|
250
|
+
if not handler:
|
|
251
|
+
return [build_error_response(msg.req, f"Method '{method_name}' not implemented")]
|
|
252
|
+
|
|
253
|
+
try:
|
|
254
|
+
return handler(msg.req, args, rpc_type)
|
|
255
|
+
except Exception as e:
|
|
256
|
+
return [build_error_response(msg.req, str(e))]
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"""fleetmesh-protocol-ssb: Secure Scuttlebutt (SSB) protocol package.
|
|
2
|
+
|
|
3
|
+
Conforms to ProtocolPackage (fleetmesh_core.wire.interfaces.ProtocolPackage).
|
|
4
|
+
Integrates the SSB sidecar daemon, client, MuxRPC routing, and SSBRung
|
|
5
|
+
into the Fleetmesh protocol host and transport ladder.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from fleetmesh_core.wire import spelling # noqa: E402
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
from typing import Any, Mapping, Optional
|
|
14
|
+
|
|
15
|
+
from fleetmesh_core.crypto.ssb import (
|
|
16
|
+
SSB_MAINNET_NETWORK_KEY,
|
|
17
|
+
SSBCryptoError,
|
|
18
|
+
format_ssb_feed_id,
|
|
19
|
+
parse_ssb_feed_id,
|
|
20
|
+
)
|
|
21
|
+
from fleetmesh_core.wire.interfaces import (
|
|
22
|
+
ProtocolHealth,
|
|
23
|
+
ProtocolHostRouter,
|
|
24
|
+
ProtocolIdentityAdapter,
|
|
25
|
+
)
|
|
26
|
+
from node.protocols.base import Ed25519IdentityAdapter
|
|
27
|
+
from node.transport.ssb_rung import SSBRung
|
|
28
|
+
from sidecar.fleetmesh_ssb import SSBSidecarClient, SSBSidecarDaemon
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
'SSBIdentityAdapter',
|
|
32
|
+
'SSBProtocolPackage',
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SSBIdentityAdapter(Ed25519IdentityAdapter):
|
|
37
|
+
"""Identity and assertion adapter for Secure Scuttlebutt (@pubkey.ed25519)."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, private_key: Any = None, feed_id: Optional[str] = None):
|
|
40
|
+
super().__init__(private_key=private_key)
|
|
41
|
+
self._feed_id = feed_id
|
|
42
|
+
if self.private_key is not None and not self._feed_id and hasattr(self.private_key, 'public_key'):
|
|
43
|
+
pk_raw = self.private_key.public_key().public_bytes_raw()
|
|
44
|
+
self._feed_id = format_ssb_feed_id(pk_raw)
|
|
45
|
+
|
|
46
|
+
def resolve_id(self, uri: str) -> Optional[str]:
|
|
47
|
+
"""Resolves SSB feed ID from raw feed ID or ssb: URI."""
|
|
48
|
+
clean = uri.strip()
|
|
49
|
+
if clean.startswith("ssb:"):
|
|
50
|
+
clean = clean[4:]
|
|
51
|
+
if clean.startswith("@") and clean.endswith(".ed25519"):
|
|
52
|
+
try:
|
|
53
|
+
parse_ssb_feed_id(clean)
|
|
54
|
+
return clean
|
|
55
|
+
except (SSBCryptoError, ValueError):
|
|
56
|
+
return None
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
def verify_assertion(self, payload: bytes, signature: bytes, pubkey: str) -> bool:
|
|
60
|
+
try:
|
|
61
|
+
if pubkey.startswith("@") and pubkey.endswith(".ed25519"):
|
|
62
|
+
pk_bytes = parse_ssb_feed_id(pubkey)
|
|
63
|
+
elif spelling.is_hex(pubkey, 64, upper=True):
|
|
64
|
+
pk_bytes = bytes.fromhex(pubkey)
|
|
65
|
+
else:
|
|
66
|
+
pk_bytes = pubkey.encode('utf-8')
|
|
67
|
+
except (SSBCryptoError, ValueError):
|
|
68
|
+
return False
|
|
69
|
+
return self._verify_ed25519_bytes(payload, signature, pk_bytes)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class SSBProtocolPackage:
|
|
73
|
+
"""The Secure Scuttlebutt (SSB) protocol suite for Fleetmesh."""
|
|
74
|
+
|
|
75
|
+
name: str = 'ssb'
|
|
76
|
+
version: str = '1.0.0'
|
|
77
|
+
standards: tuple[str, ...] = (
|
|
78
|
+
'ssb',
|
|
79
|
+
'SSB-SHS',
|
|
80
|
+
'SSB-BoxStream',
|
|
81
|
+
'SSB-MuxRPC',
|
|
82
|
+
'secret-handshake',
|
|
83
|
+
'boxstream',
|
|
84
|
+
'muxrpc',
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
node_dir: Optional[str] = None,
|
|
90
|
+
socket_path: Optional[str] = None,
|
|
91
|
+
tcp_host: str = "127.0.0.1",
|
|
92
|
+
tcp_port: int = 8008,
|
|
93
|
+
network_key: bytes = SSB_MAINNET_NETWORK_KEY,
|
|
94
|
+
secret_key_bytes: Optional[bytes] = None,
|
|
95
|
+
sidecar_client: Optional[SSBSidecarClient] = None,
|
|
96
|
+
auto_start_sidecar: bool = False,
|
|
97
|
+
private_key: Optional[Any] = None,
|
|
98
|
+
):
|
|
99
|
+
self.node_dir = node_dir or "/tmp/fleetmesh-ssb"
|
|
100
|
+
self.socket_path = socket_path or os.path.join(self.node_dir, "ssb.sock")
|
|
101
|
+
self.tcp_host = tcp_host
|
|
102
|
+
self.tcp_port = tcp_port
|
|
103
|
+
self.network_key = network_key
|
|
104
|
+
self.secret_key_bytes = secret_key_bytes
|
|
105
|
+
self.private_key = private_key
|
|
106
|
+
self.auto_start_sidecar = auto_start_sidecar
|
|
107
|
+
|
|
108
|
+
if self.private_key is not None and not self.secret_key_bytes:
|
|
109
|
+
try:
|
|
110
|
+
self.secret_key_bytes = self.private_key.private_bytes_raw()
|
|
111
|
+
except Exception:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
self._client = sidecar_client
|
|
115
|
+
self._daemon: Optional[SSBSidecarDaemon] = None
|
|
116
|
+
self._host: Optional[ProtocolHostRouter] = None
|
|
117
|
+
self._enabled: bool = True
|
|
118
|
+
self.config: Mapping[str, Any] = {}
|
|
119
|
+
|
|
120
|
+
def configure(self, config: Mapping[str, Any]) -> None:
|
|
121
|
+
self.config = dict(config)
|
|
122
|
+
self._enabled = self.config.get('enabled', True)
|
|
123
|
+
if 'socket_path' in self.config:
|
|
124
|
+
self.socket_path = self.config['socket_path']
|
|
125
|
+
if 'tcp_host' in self.config:
|
|
126
|
+
self.tcp_host = self.config['tcp_host']
|
|
127
|
+
if 'tcp_port' in self.config:
|
|
128
|
+
self.tcp_port = self.config['tcp_port']
|
|
129
|
+
if 'auto_start_sidecar' in self.config:
|
|
130
|
+
self.auto_start_sidecar = self.config['auto_start_sidecar']
|
|
131
|
+
if 'network_key' in self.config:
|
|
132
|
+
nk = self.config['network_key']
|
|
133
|
+
self.network_key = bytes.fromhex(nk) if isinstance(nk, str) else nk
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def client(self) -> Optional[SSBSidecarClient]:
|
|
137
|
+
if self._client is not None:
|
|
138
|
+
return self._client
|
|
139
|
+
if os.path.exists(self.socket_path):
|
|
140
|
+
self._client = SSBSidecarClient(self.socket_path)
|
|
141
|
+
return self._client
|
|
142
|
+
|
|
143
|
+
def identity_adapter(self, keystore: Any = None) -> Optional[ProtocolIdentityAdapter]:
|
|
144
|
+
priv = self.private_key
|
|
145
|
+
if priv is None and keystore is not None:
|
|
146
|
+
# Check if keystore has ed25519 key
|
|
147
|
+
priv = getattr(keystore, 'ed25519_sk', None)
|
|
148
|
+
return SSBIdentityAdapter(private_key=priv)
|
|
149
|
+
|
|
150
|
+
def mount_ingress(self, host: ProtocolHostRouter) -> None:
|
|
151
|
+
if not self._enabled:
|
|
152
|
+
return
|
|
153
|
+
self._host = host
|
|
154
|
+
|
|
155
|
+
# Register status inspection route for HTTP multiplexer
|
|
156
|
+
def _handle_ssb_status(conn: Any, req: Any = None) -> Any:
|
|
157
|
+
st = self.health()
|
|
158
|
+
payload = {
|
|
159
|
+
"healthy": st.healthy,
|
|
160
|
+
"status": st.status,
|
|
161
|
+
"connections_active": st.connections_active,
|
|
162
|
+
"messages_in": st.messages_in,
|
|
163
|
+
"messages_out": st.messages_out,
|
|
164
|
+
"errors": list(st.errors),
|
|
165
|
+
"socket_path": self.socket_path,
|
|
166
|
+
"tcp_port": self.tcp_port,
|
|
167
|
+
}
|
|
168
|
+
body = json.dumps(payload, indent=2).encode('utf-8')
|
|
169
|
+
if conn is not None and hasattr(conn, 'sendall'):
|
|
170
|
+
from node.transport import ws
|
|
171
|
+
ws.http_response(conn, "200 OK", body, "application/json")
|
|
172
|
+
return True
|
|
173
|
+
return 200, {"Content-Type": "application/json"}, body
|
|
174
|
+
|
|
175
|
+
if hasattr(host, 'mount_route'):
|
|
176
|
+
host.mount_route('/ssb/status', _handle_ssb_status, methods=('GET',), owner=self.name)
|
|
177
|
+
elif hasattr(host, 'register_route'):
|
|
178
|
+
host.register_route("GET", "/ssb/status", _handle_ssb_status, owner=self.name)
|
|
179
|
+
|
|
180
|
+
def transport_rung(self, context: Any = None) -> Optional[Any]:
|
|
181
|
+
if not self._enabled:
|
|
182
|
+
return None
|
|
183
|
+
router = getattr(context, 'router', None) or context
|
|
184
|
+
return SSBRung(
|
|
185
|
+
router=router,
|
|
186
|
+
sidecar_client=self.client,
|
|
187
|
+
socket_path=self.socket_path,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def compartments(self) -> tuple[type[Any], ...]:
|
|
191
|
+
return ()
|
|
192
|
+
|
|
193
|
+
def start(self) -> None:
|
|
194
|
+
if not self._enabled:
|
|
195
|
+
return
|
|
196
|
+
if self.auto_start_sidecar and self._daemon is None:
|
|
197
|
+
self._daemon = SSBSidecarDaemon(
|
|
198
|
+
node_dir=self.node_dir,
|
|
199
|
+
tcp_port=self.tcp_port,
|
|
200
|
+
bind_host=self.tcp_host,
|
|
201
|
+
uds_path=self.socket_path,
|
|
202
|
+
network_key=self.network_key,
|
|
203
|
+
secret_key_bytes=self.secret_key_bytes,
|
|
204
|
+
)
|
|
205
|
+
self._daemon.start()
|
|
206
|
+
self.tcp_port = self._daemon.tcp_port
|
|
207
|
+
self._client = SSBSidecarClient(self.socket_path)
|
|
208
|
+
|
|
209
|
+
def stop(self) -> None:
|
|
210
|
+
if self._client is not None:
|
|
211
|
+
self._client.close()
|
|
212
|
+
self._client = None
|
|
213
|
+
if self._daemon is not None:
|
|
214
|
+
self._daemon.stop()
|
|
215
|
+
self._daemon = None
|
|
216
|
+
|
|
217
|
+
def health(self) -> ProtocolHealth:
|
|
218
|
+
if not self._enabled:
|
|
219
|
+
return ProtocolHealth(
|
|
220
|
+
healthy=True,
|
|
221
|
+
status="disabled",
|
|
222
|
+
connections_active=0,
|
|
223
|
+
messages_in=0,
|
|
224
|
+
messages_out=0,
|
|
225
|
+
errors=(),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
client = self.client
|
|
229
|
+
if client is not None and os.path.exists(self.socket_path):
|
|
230
|
+
try:
|
|
231
|
+
st = client.status()
|
|
232
|
+
if st.get('ok'):
|
|
233
|
+
return ProtocolHealth(
|
|
234
|
+
healthy=True,
|
|
235
|
+
status="serving",
|
|
236
|
+
connections_active=st.get('peers_connected', 0),
|
|
237
|
+
messages_in=st.get('messages_count', 0),
|
|
238
|
+
messages_out=0,
|
|
239
|
+
errors=(),
|
|
240
|
+
)
|
|
241
|
+
except Exception as e:
|
|
242
|
+
return ProtocolHealth(
|
|
243
|
+
healthy=False,
|
|
244
|
+
status="unreachable",
|
|
245
|
+
connections_active=0,
|
|
246
|
+
messages_in=0,
|
|
247
|
+
messages_out=0,
|
|
248
|
+
errors=(str(e),),
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
return ProtocolHealth(
|
|
252
|
+
healthy=True,
|
|
253
|
+
status="configured",
|
|
254
|
+
connections_active=0,
|
|
255
|
+
messages_in=0,
|
|
256
|
+
messages_out=0,
|
|
257
|
+
errors=(),
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
def descriptor_capabilities(self) -> tuple[tuple[str, str], ...]:
|
|
261
|
+
if not self._enabled:
|
|
262
|
+
return ()
|
|
263
|
+
return (
|
|
264
|
+
('c', 'ssb'),
|
|
265
|
+
('c', 'shs'),
|
|
266
|
+
('c', 'muxrpc'),
|
|
267
|
+
)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""FleetMesh Node Textile Protocol Package (`node.protocols.textile`)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
# The stores and route handlers live in the fleetmesh-protocols package
|
|
5
|
+
# (fleetmesh_protocols.textile); this package re-exports them so node code and
|
|
6
|
+
# the protocol router keep their import paths.
|
|
7
|
+
|
|
8
|
+
from fleetmesh_protocols.textile.fiber_routes import HttpResult, JSON_CT, binary_http_response, handle_fiber_http, is_fiber_route
|
|
9
|
+
from fleetmesh_protocols.textile.fiber_store import (
|
|
10
|
+
FIBER_KINDS,
|
|
11
|
+
INTERACTION_KINDS,
|
|
12
|
+
MAX_FIBER_BYTES,
|
|
13
|
+
MAX_OWNER_BYTES,
|
|
14
|
+
MAX_UPLOAD_BODY_BYTES,
|
|
15
|
+
PAYLOAD_KINDS,
|
|
16
|
+
VISIBILITIES,
|
|
17
|
+
StandaloneFiberStore,
|
|
18
|
+
)
|
|
19
|
+
from fleetmesh_protocols.textile.hosted_relay import PROTOCOL_DIGEST, PROTOCOL_VERSION, HostedLeafRelay
|
|
20
|
+
from fleetmesh_protocols.textile.leaf_relay import (
|
|
21
|
+
KIND_FABRIC,
|
|
22
|
+
KIND_FIBER,
|
|
23
|
+
KIND_QUILT,
|
|
24
|
+
KIND_STRAND,
|
|
25
|
+
NEG_BUCKETS,
|
|
26
|
+
NEG_FINGERPRINT,
|
|
27
|
+
NEG_ID_LIST,
|
|
28
|
+
NEG_INFINITY,
|
|
29
|
+
NEG_LIST_THRESHOLD,
|
|
30
|
+
NEG_SKIP,
|
|
31
|
+
NEG_VERSION,
|
|
32
|
+
WS_GUID,
|
|
33
|
+
NegBound,
|
|
34
|
+
NegentropyServer,
|
|
35
|
+
build_engine_textile_inventory,
|
|
36
|
+
canonical_bao_hex,
|
|
37
|
+
decode_neg_message,
|
|
38
|
+
decode_varint,
|
|
39
|
+
det_hex,
|
|
40
|
+
encode_neg_message,
|
|
41
|
+
encode_varint,
|
|
42
|
+
neg_fingerprint,
|
|
43
|
+
serve_relay_websocket,
|
|
44
|
+
)
|
|
45
|
+
from fleetmesh_protocols.textile.quilt_routes import handle_quilt_http, is_quilt_route
|
|
46
|
+
from fleetmesh_protocols.textile.quilt_store import (
|
|
47
|
+
AUDIENCE_RANK,
|
|
48
|
+
AUDIENCES,
|
|
49
|
+
MAX_VIEW_JSON_BYTES,
|
|
50
|
+
StandaloneQuiltStore,
|
|
51
|
+
compute_fabric_root,
|
|
52
|
+
compute_quilt_root,
|
|
53
|
+
group_owner_id,
|
|
54
|
+
validate_quilt_view,
|
|
55
|
+
)
|
|
56
|
+
from .transducers import PROTOCOL_FAMILIES, PythonProtocolRouter, default_python_protocol_router
|
|
57
|
+
|
|
58
|
+
__all__ = [
|
|
59
|
+
"HttpResult",
|
|
60
|
+
"JSON_CT",
|
|
61
|
+
"binary_http_response",
|
|
62
|
+
"handle_fiber_http",
|
|
63
|
+
"is_fiber_route",
|
|
64
|
+
"FIBER_KINDS",
|
|
65
|
+
"INTERACTION_KINDS",
|
|
66
|
+
"MAX_FIBER_BYTES",
|
|
67
|
+
"MAX_OWNER_BYTES",
|
|
68
|
+
"MAX_UPLOAD_BODY_BYTES",
|
|
69
|
+
"PAYLOAD_KINDS",
|
|
70
|
+
"VISIBILITIES",
|
|
71
|
+
"StandaloneFiberStore",
|
|
72
|
+
"PROTOCOL_DIGEST",
|
|
73
|
+
"PROTOCOL_VERSION",
|
|
74
|
+
"HostedLeafRelay",
|
|
75
|
+
"KIND_FABRIC",
|
|
76
|
+
"KIND_FIBER",
|
|
77
|
+
"KIND_QUILT",
|
|
78
|
+
"KIND_STRAND",
|
|
79
|
+
"NEG_BUCKETS",
|
|
80
|
+
"NEG_FINGERPRINT",
|
|
81
|
+
"NEG_ID_LIST",
|
|
82
|
+
"NEG_INFINITY",
|
|
83
|
+
"NEG_LIST_THRESHOLD",
|
|
84
|
+
"NEG_SKIP",
|
|
85
|
+
"NEG_VERSION",
|
|
86
|
+
"WS_GUID",
|
|
87
|
+
"NegBound",
|
|
88
|
+
"NegentropyServer",
|
|
89
|
+
"build_engine_textile_inventory",
|
|
90
|
+
"canonical_bao_hex",
|
|
91
|
+
"det_hex",
|
|
92
|
+
"decode_neg_message",
|
|
93
|
+
"decode_varint",
|
|
94
|
+
"encode_neg_message",
|
|
95
|
+
"encode_varint",
|
|
96
|
+
"neg_fingerprint",
|
|
97
|
+
"serve_relay_websocket",
|
|
98
|
+
"handle_quilt_http",
|
|
99
|
+
"is_quilt_route",
|
|
100
|
+
"AUDIENCE_RANK",
|
|
101
|
+
"AUDIENCES",
|
|
102
|
+
"MAX_VIEW_JSON_BYTES",
|
|
103
|
+
"StandaloneQuiltStore",
|
|
104
|
+
"compute_fabric_root",
|
|
105
|
+
"compute_quilt_root",
|
|
106
|
+
"group_owner_id",
|
|
107
|
+
"validate_quilt_view",
|
|
108
|
+
"PROTOCOL_FAMILIES",
|
|
109
|
+
"PythonProtocolRouter",
|
|
110
|
+
"default_python_protocol_router",
|
|
111
|
+
]
|