p2p_dart 1.0.0 copy "p2p_dart: ^1.0.0" to clipboard
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 #

pub version Dart SDK License: MIT Tests

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:

  1. DTLS β€” DTLS 1.2 (handled by WebRTC engine) with certificate fingerprint exchange.
  2. ECDH Key Exchange β€” Ephemeral P-256 key pairs; shared secret derived per-session.
  3. AES-256-GCM β€” All application messages encrypted end-to-end.
  4. HMAC-SHA256 β€” Each encrypted envelope is authenticated.
  5. 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_dns package
  • ❌ Noise protocol upgrade for handshake
  • ❌ QUIC transport support
  • ❌ Pub.dev publication
  • ❌ GitHub Actions CI workflow

🀝 Contributing #

  1. Fork the repo.
  2. Create a feature branch: git checkout -b feat/my-feature.
  3. Run tests: dart test.
  4. Open a PR against main.

πŸ“„ License #

MIT Β© 2026 p2p_dart contributors β€” see LICENSE.

1
likes
120
points
7
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

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 central server.

Repository (GitHub)
View/report issues

Topics

#dart #p2p #webrtc #dht #kademlia

License

MIT (license)

Dependencies

async, collection, convert, crypto, http, logging, pointycastle, rxdart, typed_data, uuid

More

Packages that depend on p2p_dart