mirror of
https://github.com/sigcn/pg.git
synced 2025-09-26 19:01:11 +08:00
disco: Peermap to Server
This commit is contained in:
@@ -278,11 +278,7 @@ func (v *P2PVPN) listenPacketConn(ctx context.Context) (c *p2p.PacketConn, err e
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
peermapURL, err := url.Parse(v.Config.Server)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
peermap, err := disco.NewPeermap(peermapURL, secretStore)
|
||||
peermap, err := disco.NewServer(v.Config.Server, secretStore)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@@ -10,43 +10,29 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Peermap struct {
|
||||
store SecretStore
|
||||
server *url.URL
|
||||
type Server struct {
|
||||
Secret SecretStore
|
||||
URL string
|
||||
}
|
||||
|
||||
func NewPeermap(server *url.URL, store SecretStore) (*Peermap, error) {
|
||||
func NewServer(serverURL string, store SecretStore) (*Server, error) {
|
||||
if store == nil {
|
||||
return nil, errors.New("secret store is required")
|
||||
}
|
||||
if server == nil {
|
||||
return nil, errors.New("peermap server is required")
|
||||
|
||||
server, err := url.Parse(serverURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !slices.Contains([]string{"https", "wss", "http", "ws"}, server.Scheme) {
|
||||
return nil, fmt.Errorf("invalid peermap server %s", server.String())
|
||||
return nil, fmt.Errorf("unsupport server protocol: %s", server.String())
|
||||
}
|
||||
return &Peermap{
|
||||
store: store,
|
||||
server: server,
|
||||
return &Server{
|
||||
Secret: store,
|
||||
URL: serverURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewPeermapURL(serverURL string, store SecretStore) (*Peermap, error) {
|
||||
sURL, err := url.Parse(serverURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid peermap url: %w", err)
|
||||
}
|
||||
return NewPeermap(sURL, store)
|
||||
}
|
||||
|
||||
func (s *Peermap) SecretStore() SecretStore {
|
||||
return s.store
|
||||
}
|
||||
|
||||
func (s *Peermap) String() string {
|
||||
return s.server.String()
|
||||
}
|
||||
|
||||
type SecretStore interface {
|
||||
NetworkSecret() (NetworkSecret, error)
|
||||
UpdateNetworkSecret(NetworkSecret) error
|
@@ -1,6 +1,7 @@
|
||||
package ws
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
@@ -29,7 +30,7 @@ var (
|
||||
|
||||
type WSConn struct {
|
||||
rawConn atomic.Pointer[websocket.Conn]
|
||||
server *disco.Peermap
|
||||
server *disco.Server
|
||||
connectedServer string
|
||||
peerID disco.PeerID
|
||||
metadata url.Values
|
||||
@@ -197,7 +198,7 @@ func (c *WSConn) Unregister(ctr disco.Controller) {
|
||||
}
|
||||
|
||||
func (c *WSConn) dial(ctx context.Context, server string) error {
|
||||
networkSecret, err := c.server.SecretStore().NetworkSecret()
|
||||
networkSecret, err := cmp.Or[disco.SecretStore](c.server.Secret, &disco.NetworkSecret{}).NetworkSecret()
|
||||
if err != nil {
|
||||
return fmt.Errorf("get network secret failed: %w", err)
|
||||
}
|
||||
@@ -207,7 +208,7 @@ func (c *WSConn) dial(ctx context.Context, server string) error {
|
||||
handshake.Set("X-Nonce", disco.NewNonce())
|
||||
handshake.Set("X-Metadata", c.metadata.Encode())
|
||||
if server == "" {
|
||||
server = c.server.String()
|
||||
server = c.server.URL
|
||||
}
|
||||
peermap, err := url.Parse(server)
|
||||
if err != nil {
|
||||
@@ -474,7 +475,7 @@ func (c *WSConn) writeWS(messageType int, data []byte) error {
|
||||
|
||||
func (c *WSConn) updateNetworkSecret(secret disco.NetworkSecret) {
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := c.server.SecretStore().UpdateNetworkSecret(secret); err != nil {
|
||||
if err := c.server.Secret.UpdateNetworkSecret(secret); err != nil {
|
||||
slog.Error("[WS] NetworkSecretUpdate", "err", err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
@@ -484,7 +485,7 @@ func (c *WSConn) updateNetworkSecret(secret disco.NetworkSecret) {
|
||||
slog.Error("[WS] NetworkSecretUpdate give up", "secret", secret)
|
||||
}
|
||||
|
||||
func DialPeermap(ctx context.Context, server *disco.Peermap, peerID disco.PeerID, metadata url.Values) (*WSConn, error) {
|
||||
func DialPeermap(ctx context.Context, server *disco.Server, peerID disco.PeerID, metadata url.Values) (*WSConn, error) {
|
||||
wsConn := &WSConn{
|
||||
server: server,
|
||||
peerID: peerID,
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
"github.com/sigcn/pg/disco"
|
||||
"github.com/sigcn/pg/p2p"
|
||||
@@ -18,12 +17,8 @@ type PublicNetwork struct {
|
||||
}
|
||||
|
||||
func (pn *PublicNetwork) ListenPacket(udpPort int) (net.PacketConn, error) {
|
||||
pmapURL, err := url.Parse(pn.Server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid peermap URL: %w", err)
|
||||
}
|
||||
network := cmp.Or(pn.Name, "pubnet")
|
||||
pmap, err := disco.NewPeermap(pmapURL, &disco.NetworkSecret{Network: network, Secret: network})
|
||||
pmap, err := disco.NewServer(pn.Server, &disco.NetworkSecret{Network: network, Secret: network})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create peermap failed: %w", err)
|
||||
}
|
||||
|
@@ -1,9 +1,11 @@
|
||||
# p2p library
|
||||
|
||||
### Example
|
||||
|
||||
### Peer1 (act as echo server)
|
||||
|
||||
```go
|
||||
peermapURL := "wss://synf.in/pg"
|
||||
serverURL := "wss://synf.in/pg"
|
||||
|
||||
intent, err := network.JoinOIDC(oidc.ProviderGoogle, peermapURL)
|
||||
if err != nil {
|
||||
@@ -15,19 +17,14 @@ if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pmServer, err := peer.NewPeermapURL(peermapURL, networkSecret)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// peerID is a unique string (less than 256bytes)
|
||||
packetConn, err := p2p.ListenPacket(pmServer, p2p.ListenPeerID("uniqueString"))
|
||||
packetConn, err := p2p.ListenPacket(disco.NewServer(serverURL, networkSecret), p2p.ListenPeerID("uniqueString"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// unreliability echo server
|
||||
buf := make([]byte, 1024)
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, peerID, err := packetConn.ReadFrom(buf)
|
||||
if err != nil {
|
||||
@@ -41,11 +38,12 @@ for {
|
||||
}
|
||||
```
|
||||
|
||||
### Peer2
|
||||
### Peer2
|
||||
|
||||
```go
|
||||
...
|
||||
|
||||
packetConn, err := p2p.ListenPacket(pmServer)
|
||||
packetConn, err := p2p.ListenPacket(disco.NewServer(serverURL, networkSecret))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@@ -388,12 +388,12 @@ func (c *PacketConn) runControlEventLoop() {
|
||||
}
|
||||
|
||||
// ListenPacket same as ListenPacketContext, but no context required
|
||||
func ListenPacket(peermap *disco.Peermap, opts ...Option) (*PacketConn, error) {
|
||||
func ListenPacket(peermap *disco.Server, opts ...Option) (*PacketConn, error) {
|
||||
return ListenPacketContext(context.Background(), peermap, opts...)
|
||||
}
|
||||
|
||||
// ListenPacketContext listen the p2p network for read/write packets
|
||||
func ListenPacketContext(ctx context.Context, peermap *disco.Peermap, opts ...Option) (*PacketConn, error) {
|
||||
func ListenPacketContext(ctx context.Context, peermap *disco.Server, opts ...Option) (*PacketConn, error) {
|
||||
id := make([]byte, 16)
|
||||
rand.Read(id)
|
||||
cfg := Config{
|
||||
|
Reference in New Issue
Block a user