97 lines
3.7 KiB
Markdown
97 lines
3.7 KiB
Markdown
*/# PeerNet -- peer-to-peer communication without the network
|
|
|
|
PeerNet is a protocol and server software which let clients communicate directly with each other without required a lot of configuration or system permissions. It leverages WebRTC to create data channels between peers, and uses a simple protocol to let clients advertise services for other clients to connect with. Initially developed as an attempt to simplify a home security system, the reference client implementations offer:
|
|
|
|
- Security camera server and client
|
|
- Sensor server and client (i.e., to monitor external temperature and humidity)
|
|
- File server and client (i.e., to transfer security footage)
|
|
|
|
## PeerNet protocol
|
|
|
|
PeerNet clients uses JSON or Protobuf to connect to the PeerNet server (signaling server, in WebRTC terms). They send messages advertising what they can do, and poll the server for clients who would like to establish connections. The server collects enough informaion for clients to identify the services, but no other information.
|
|
|
|
One minor goal in this API design is to minimize the number of messages that need to be sent to establish the connection. That means some operations violate REST API semantics; standard REST API features are also available for those who are pure of heart. We define these resources:
|
|
|
|
- Room: a logical grouping of servers, and the primary means of discovering a server
|
|
- Server: intended to represent a server, which may have multiple resources
|
|
- Service: a service on the server; a server may have multiple services
|
|
- Knock: a request to create a connection with the server; named to avoid stuttering and save keystrokes
|
|
|
|
Sample server flow:
|
|
|
|
```pyton
|
|
import requests
|
|
|
|
url = 'https://myserver.local'
|
|
|
|
response = requests.post(url + '/server', '''
|
|
{
|
|
"unique_id": "
|
|
}
|
|
''')
|
|
```
|
|
|
|
The protocol is define below in Protobuf, but is also availabe [here] in OpenAPI format.
|
|
|
|
```proto2
|
|
syntax = "proto2";
|
|
package peernet
|
|
|
|
service PeerNetService {
|
|
rpc CreateRoom(CreateRoomRequest) returns (CreateRoomResponse);
|
|
rpc DeleteRoom(DeleteRoomRequest) return (DeleteRoomResponse);
|
|
|
|
rpc CreateServer(CreateServerRequest) returns (CreateServerResponse);
|
|
rpc DeleteServer(DeleteServerRequest) returns (DeleteServerResponse);
|
|
rpc ListServers(ListServersRequest) returns (ListServersResponse);
|
|
|
|
rpc CreateService(CreateServiceRequest) returns (CreateServiceResponse);
|
|
rpc DeleteService(DeleteServiceRequest) returns (DeleteServiceResponse);
|
|
rpc UpdateService(UpdateServiceRequest) returns (UpdateServiceResponse);
|
|
|
|
rpc CreateKnock(CreateKnockRequest) returns (CreateKnockResponse);
|
|
rpc DeleteKnock(DeleteKnockRequest) returns (DeleteKnockResponse);
|
|
rpc GetKnock(GetKnockRequest) returns (Knock);
|
|
rpc ListKnocks(ListKnocksRequest) returns (ListKnocksResponse);
|
|
}
|
|
|
|
message Room {
|
|
string unique_id = 1;
|
|
string display_name = 2;
|
|
}
|
|
|
|
message Server {
|
|
string unique_id = 1;
|
|
|
|
string room = 2;
|
|
|
|
string display_name = 2;
|
|
}
|
|
|
|
message Service {
|
|
string protocol = 1;
|
|
string version = 2;
|
|
|
|
// Used to define custom fields per-protocol/version.
|
|
// We use unverified extensions because this system is meant
|
|
// to be distributed, with no central owner, hence, no singular
|
|
// authority to hand out field numbers. Instead, implementations
|
|
// should use the protocol/version to scope what values are expected.
|
|
extensions 100 to max [verification = UNVERIFIED];
|
|
}
|
|
|
|
message Knock {
|
|
|
|
repeated IceCandidate ice_candidates = 1;
|
|
}
|
|
|
|
message IceCandidate {
|
|
// Copied from https://pkg.go.dev/github.com/pion/webrtc/v4#ICECandidateInit
|
|
string candidate = 1;
|
|
optional string sdp_mid = 2;
|
|
optional int32 sdp_line_index = 3;
|
|
optional string username_fragment = 4;
|
|
}
|
|
|
|
|
|
``` |