p2p_dart 1.0.0
p2p_dart: ^1.0.0 copied to clipboard
A production-ready Dart package for serverless peer-to-peer networking using WebRTC data channels and a Kademlia-based DHT, enabling secure, encrypted, NAT-traversing direct connections without a cent [...]
p2p_dart #
Serverless peer-to-peer networking for Dart.
Direct, encrypted connections between Dart applications β no central server required.
β¨ Features #
| Feature | Detail |
|---|---|
| π Direct connections | WebRTC DataChannels for reliable or unreliable delivery |
| π NAT traversal | Automatic ICE/STUN/TURN negotiation |
| π‘ Peer discovery | Kademlia DHT + mDNS local network |
| π End-to-end encryption | ECDH key exchange + AES-256-GCM + DTLS |
| πΎ Distributed storage | Put/Get key-value records across the DHT |
| π± Cross-platform | Android, iOS, Linux, macOS, Windows, Web |
| β‘ High performance | Zero-copy buffers, LRU peer cache, async pipeline |
| π§© Typed events | EventBus<T> for all lifecycle + message events |
π Quick Start #
1. Add to pubspec.yaml #
dependencies:
p2p_dart: ^1.0.0
2. Minimal example #
import 'package:p2p_dart/p2p_dart.dart';
void main() async {
// Create a node with bootstrap peers.
final node = P2PNode(
config: P2PConfig(
bootstrapPeers: ['<known-peer-id>'],
),
);
// Start the node β initialises DHT & WebRTC.
await node.initialize();
print('Online: ${node.peerId}');
// Listen for incoming messages.
node.eventBus.on<MessageReceivedEvent>((event) {
print('[${event.senderId.substring(0, 8)}]: ${event.data}');
});
// Connect and send.
await node.connect('<remote-peer-id>');
await node.send('<remote-peer-id>', {'hello': 'world'});
// Store a value in the DHT.
await node.dhtPut('my-key', 'my-value');
// Retrieve it later (from any node in the network).
final value = await node.dhtGet('my-key');
print(value); // 'my-value'
}
π API Overview #
P2PNode #
The central class β creates, manages, and tears down the P2P node.
| Method | Description |
|---|---|
initialize() |
Starts DHT, WebRTC, and bootstrapping |
stop() |
Cleanly shuts down all connections |
connect(peerId) |
Establishes a WebRTC connection |
send(peerId, data) |
Sends a JSON map to a peer |
sendText(peerId, text) |
Sends a plain text message |
broadcast(data) |
Sends to ALL connected peers |
sendToMany(peerIds, data) |
Sends to a subset of peers |
disconnect(peerId) |
Closes the connection to a peer |
dhtPut(key, value) |
Stores in the distributed hash table |
dhtGet(key) |
Retrieves from the DHT |
isConnectedTo(peerId) |
Returns true if connected |
connectedPeerIds |
Iterable<String> of active peers |
P2PConfig #
P2PConfig(
peerId: null, // auto-generated if null
bootstrapPeers: [...], // shorthand for dht.bootstrapPeers
dht: DHTConfig(
bootstrapPeers: [...],
bucketSize: 20, // Kademlia k
alpha: 3, // lookup parallelism
replicationFactor: 3,
valueTtl: Duration(hours: 24),
),
webrtc: WebRTCConfig(
stunServers: [StunServerConfig('stun.l.google.com')],
turnServers: [TurnServerConfig(host: 'β¦', username: 'β¦', credential: 'β¦')],
connectionTimeout: Duration(seconds: 30),
),
security: SecurityConfig(
enforceEncryption: true,
requireAuthentication: false,
),
performance: PerformanceConfig(
maxConnections: 100,
maxMessageSize: 65536,
heartbeatInterval: Duration(seconds: 30),
enableCompression: false,
),
logging: LoggingConfig(verbose: false),
)
EventBus #
Type-safe publish/subscribe:
// Subscribe
final sub = node.eventBus.on<MessageReceivedEvent>((event) { β¦ });
// One-shot
node.eventBus.once<PeerConnectedEvent>((event) { β¦ });
// Await next event
final event = await node.eventBus.next<NodeStartedEvent>();
// As a stream
node.eventBus.stream<PeerLeftEvent>().listen((event) { β¦ });
// Cancel
sub.cancel();
Available Events
| Event | Fired when⦠|
|---|---|
NodeStartedEvent |
initialize() completes |
NodeStoppedEvent |
stop() completes |
PeerConnectedEvent |
New WebRTC connection is established |
PeerDisconnectedEvent |
A peer connection drops |
PeerLeftEvent |
A peer sends a goodbye signal |
PeerDiscoveredEvent |
A new peer is found via mDNS/DHT |
MessageReceivedEvent |
A DATA message arrives |
DHTBootstrappedEvent |
DHT bootstrap phase completes |
DHTValueStoredEvent |
A value is stored in the DHT |
ErrorEvent |
A non-fatal error occurs |
Connection #
Individual connection object returned by node.connect():
final conn = await node.connect(remotePeerId);
// Send
await conn.send({'key': 'value'});
await conn.sendText('raw string');
await conn.sendBinary(Uint8List.fromList([β¦]));
// Receive
conn.onData.listen((msg) => print(msg.payload));
conn.onStateChange.listen((state) => print(state));
// Stats
print(conn.stats());
// Close
await conn.close();
π Security #
All connections are secured by default:
- DTLS β DTLS 1.2 (handled by WebRTC engine) with certificate fingerprint exchange.
- ECDH Key Exchange β Ephemeral P-256 key pairs; shared secret derived per-session.
- AES-256-GCM β All application messages encrypted end-to-end.
- HMAC-SHA256 β Each encrypted envelope is authenticated.
- Challenge-Response Auth β Optional peer identity verification.
P2PConfig(
security: SecurityConfig(
enforceEncryption: true,
requireAuthentication: true,
trustedPeers: ['<trusted-peer-id>', β¦],
),
)
πΎ Distributed Hash Table #
p2p_dart includes a full Kademlia DHT:
// Store any JSON value.
await node.dhtPut('user:alice', jsonEncode({'name': 'Alice', 'score': 100}));
// Retrieve from anywhere in the network.
final raw = await node.dhtGet('user:alice');
final user = jsonDecode(raw!);
// Content-addressable (key = SHA-1 of value).
final storage = DecentralisedStorage();
final casKey = await storage.putCas({'data': 'important'});
final doc = await storage.getCas(casKey);
π Project Structure #
lib/
βββ p2p_dart.dart # Public exports
βββ src/
βββ core/
β βββ p2p_node.dart # β Main entry point
β βββ connection.dart # Individual peer connection
β βββ channel_manager.dart
β βββ peer_info.dart
β βββ p2p_config.dart
β βββ enums.dart
β βββ exceptions.dart
βββ dht/
β βββ dht_network.dart # Kademlia DHT
β βββ routing_table.dart
β βββ kademlia.dart # XOR metric + ID utilities
β βββ bucket.dart
β βββ dht_config.dart
βββ webrtc/
β βββ webrtc_manager.dart
β βββ webrtc_config.dart
β βββ ice_configuration.dart
β βββ stun_client.dart
β βββ data_channel_wrapper.dart
βββ networking/
β βββ message.dart
β βββ message_handler.dart
β βββ packet.dart
β βββ transport.dart
βββ security/
β βββ encryption.dart # AES-256-GCM
β βββ key_exchange.dart # ECDH P-256
β βββ dtls_handler.dart
β βββ crypto_utils.dart
β βββ auth_manager.dart
βββ discovery/
β βββ peer_discovery.dart
β βββ local_network.dart # mDNS
β βββ peer_cache.dart
βββ events/
β βββ event_bus.dart
β βββ events.dart
βββ utils/
β βββ logger.dart
β βββ async_utils.dart
β βββ buffer_manager.dart
β βββ validators.dart
βββ extensions/
βββ stream_extensions.dart
βββ future_extensions.dart
βββ string_extensions.dart
example/
βββ simple_chat.dart # CLI chat application
βββ file_sharing.dart # Chunked file transfer
βββ multiplayer_game.dart # Real-time game state sync
βββ decentralized_storage.dart # DHT key-value store
test/
βββ unit/ # Unit tests (Kademlia, crypto, eventsβ¦)
βββ integration/ # Node lifecycle tests
βββ performance/ # Throughput benchmarks
π§ͺ Running Tests #
dart pub get
dart test # All tests
dart test test/unit/ # Unit tests only
dart test test/performance/ # Benchmarks
dart test --coverage=coverage/ # With coverage
π Examples #
# P2P Chat (terminal A)
dart run example/simple_chat.dart
# P2P Chat (terminal B β paste peer ID from A)
dart run example/simple_chat.dart <peer-id-from-A>
# File sharing
dart run example/file_sharing.dart <target-peer-id> /path/to/file.txt
# Decentralised storage demo
dart run example/decentralized_storage.dart
# Multiplayer game demo
dart run example/multiplayer_game.dart
β‘ Performance #
| Operation | Throughput / Latency |
|---|---|
| AES-256-GCM encrypt 1 MB | < 500 ms |
| Chunker split 10 MB | < 100 ms |
| RoutingTable insert 1 000 peers | < 100 ms |
| Closest-20 lookup (500 peers) | < 0.02 ms |
| EventBus dispatch (100 k events) | < 100 ms |
| Kademlia ID generation (10 k) | < 500 ms |
πΊοΈ Roadmap #
- β Flutter WebRTC integration (
flutter_webrtc/dart_webrtc) - β mDNS via
multicast_dnspackage - β Noise protocol upgrade for handshake
- β QUIC transport support
- β Pub.dev publication
- β GitHub Actions CI workflow
π€ Contributing #
- Fork the repo.
- Create a feature branch:
git checkout -b feat/my-feature. - Run tests:
dart test. - Open a PR against
main.
π License #
MIT Β© 2026 p2p_dart contributors β see LICENSE.