mirror of
https://github.com/sigcn/pg.git
synced 2025-10-05 15:26:52 +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 {
|
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
|
||||||
}
|
}
|
||||||
|
@@ -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
|
@@ -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,
|
||||||
|
@@ -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)
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
}
|
}
|
||||||
|
@@ -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{
|
||||||
|
Reference in New Issue
Block a user