disco: Peermap to Server

This commit is contained in:
rkonfj
2024-11-25 21:19:38 +08:00
parent 307e441fa1
commit b01e7cd34e
6 changed files with 30 additions and 54 deletions

View File

@@ -278,11 +278,7 @@ func (v *P2PVPN) listenPacketConn(ctx context.Context) (c *p2p.PacketConn, err e
if err != nil { if err != nil {
return return
} }
peermapURL, err := url.Parse(v.Config.Server) peermap, err := disco.NewServer(v.Config.Server, secretStore)
if err != nil {
return
}
peermap, err := disco.NewPeermap(peermapURL, secretStore)
if err != nil { if err != nil {
return return
} }

View File

@@ -10,43 +10,29 @@ import (
"time" "time"
) )
type Peermap struct { type Server struct {
store SecretStore Secret SecretStore
server *url.URL URL string
} }
func NewPeermap(server *url.URL, store SecretStore) (*Peermap, error) { func NewServer(serverURL string, store SecretStore) (*Server, error) {
if store == nil { if store == nil {
return nil, errors.New("secret store is required") 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) { 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{ return &Server{
store: store, Secret: store,
server: server, URL: serverURL,
}, nil }, 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 { type SecretStore interface {
NetworkSecret() (NetworkSecret, error) NetworkSecret() (NetworkSecret, error)
UpdateNetworkSecret(NetworkSecret) error UpdateNetworkSecret(NetworkSecret) error

View File

@@ -1,6 +1,7 @@
package ws package ws
import ( import (
"cmp"
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
@@ -29,7 +30,7 @@ var (
type WSConn struct { type WSConn struct {
rawConn atomic.Pointer[websocket.Conn] rawConn atomic.Pointer[websocket.Conn]
server *disco.Peermap server *disco.Server
connectedServer string connectedServer string
peerID disco.PeerID peerID disco.PeerID
metadata url.Values metadata url.Values
@@ -197,7 +198,7 @@ func (c *WSConn) Unregister(ctr disco.Controller) {
} }
func (c *WSConn) dial(ctx context.Context, server string) error { 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 { if err != nil {
return fmt.Errorf("get network secret failed: %w", err) 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-Nonce", disco.NewNonce())
handshake.Set("X-Metadata", c.metadata.Encode()) handshake.Set("X-Metadata", c.metadata.Encode())
if server == "" { if server == "" {
server = c.server.String() server = c.server.URL
} }
peermap, err := url.Parse(server) peermap, err := url.Parse(server)
if err != nil { if err != nil {
@@ -474,7 +475,7 @@ func (c *WSConn) writeWS(messageType int, data []byte) error {
func (c *WSConn) updateNetworkSecret(secret disco.NetworkSecret) { func (c *WSConn) updateNetworkSecret(secret disco.NetworkSecret) {
for i := 0; i < 5; i++ { 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) slog.Error("[WS] NetworkSecretUpdate", "err", err)
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
@@ -484,7 +485,7 @@ func (c *WSConn) updateNetworkSecret(secret disco.NetworkSecret) {
slog.Error("[WS] NetworkSecretUpdate give up", "secret", secret) 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{ wsConn := &WSConn{
server: server, server: server,
peerID: peerID, peerID: peerID,

View File

@@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"net/url"
"github.com/sigcn/pg/disco" "github.com/sigcn/pg/disco"
"github.com/sigcn/pg/p2p" "github.com/sigcn/pg/p2p"
@@ -18,12 +17,8 @@ type PublicNetwork struct {
} }
func (pn *PublicNetwork) ListenPacket(udpPort int) (net.PacketConn, error) { 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") 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 { if err != nil {
return nil, fmt.Errorf("create peermap failed: %w", err) return nil, fmt.Errorf("create peermap failed: %w", err)
} }

View File

@@ -1,9 +1,11 @@
# p2p library # p2p library
### Example ### Example
### Peer1 (act as echo server) ### Peer1 (act as echo server)
```go ```go
peermapURL := "wss://synf.in/pg" serverURL := "wss://synf.in/pg"
intent, err := network.JoinOIDC(oidc.ProviderGoogle, peermapURL) intent, err := network.JoinOIDC(oidc.ProviderGoogle, peermapURL)
if err != nil { if err != nil {
@@ -15,13 +17,8 @@ if err != nil {
panic(err) panic(err)
} }
pmServer, err := peer.NewPeermapURL(peermapURL, networkSecret)
if err != nil {
panic(err)
}
// peerID is a unique string (less than 256bytes) // 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 { if err != nil {
panic(err) panic(err)
} }
@@ -42,10 +39,11 @@ for {
``` ```
### Peer2 ### Peer2
```go ```go
... ...
packetConn, err := p2p.ListenPacket(pmServer) packetConn, err := p2p.ListenPacket(disco.NewServer(serverURL, networkSecret))
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -388,12 +388,12 @@ func (c *PacketConn) runControlEventLoop() {
} }
// ListenPacket same as ListenPacketContext, but no context required // 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...) return ListenPacketContext(context.Background(), peermap, opts...)
} }
// ListenPacketContext listen the p2p network for read/write packets // 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) id := make([]byte, 16)
rand.Read(id) rand.Read(id)
cfg := Config{ cfg := Config{