replace peer.Metadata with url.Values

This commit is contained in:
rkonfj 2024-05-26 19:07:18 +08:00
parent 5c03d24521
commit 02122c9a9d
6 changed files with 57 additions and 68 deletions

View File

@ -164,16 +164,17 @@ func (v *P2PVPN) listenPacketConn() (c net.PacketConn, err error) {
})
disco.SetIgnoredLocalInterfaceNamePrefixs("pg", "wg", "veth", "docker", "nerdctl", "tailscale")
disco.AddIgnoredLocalCIDRs(v.Config.AllowedIPs...)
p2pOptions := []p2p.Option{
p2p.PeerMeta("allowedIPs", v.Config.AllowedIPs),
p2p.PeerMeta("version", fmt.Sprintf("%s-%s", Version, Commit)),
p2p.ListenPeerUp(v.addPeer),
}
for _, ip := range v.Config.AllowedIPs {
p2p.PeerMeta("allowedIP", ip)
}
if len(v.Config.Peers) > 0 {
p2pOptions = append(p2pOptions, p2p.PeerSilenceMode())
}
for _, peerURL := range v.Config.Peers {
pgPeer, err := url.Parse(peerURL)
if err != nil {
@ -182,17 +183,8 @@ func (v *P2PVPN) listenPacketConn() (c net.PacketConn, err error) {
if pgPeer.Scheme != "pg" {
return nil, fmt.Errorf("unsupport scheme %s", pgPeer.Scheme)
}
extra := make(map[string]any)
for k, v := range pgPeer.Query() {
extra[k] = v[0]
}
v.addPeer(peer.ID(pgPeer.Host), peer.Metadata{
Alias1: pgPeer.Query().Get("alias1"),
Alias2: pgPeer.Query().Get("alias2"),
Extra: extra,
})
v.addPeer(peer.ID(pgPeer.Host), pgPeer.Query())
}
if v.Config.IPv4 != "" {
ipv4, err := netip.ParsePrefix(v.Config.IPv4)
if err != nil {
@ -201,7 +193,6 @@ func (v *P2PVPN) listenPacketConn() (c net.PacketConn, err error) {
disco.AddIgnoredLocalCIDRs(v.Config.IPv4)
p2pOptions = append(p2pOptions, p2p.PeerAlias1(ipv4.Addr().String()))
}
if v.Config.IPv6 != "" {
ipv6, err := netip.ParsePrefix(v.Config.IPv6)
if err != nil {
@ -210,7 +201,6 @@ func (v *P2PVPN) listenPacketConn() (c net.PacketConn, err error) {
disco.AddIgnoredLocalCIDRs(v.Config.IPv6)
p2pOptions = append(p2pOptions, p2p.PeerAlias2(ipv6.Addr().String()))
}
if v.Config.PrivateKey != "" {
p2pOptions = append(p2pOptions, p2p.ListenPeerCurve25519(v.Config.PrivateKey))
} else {
@ -233,21 +223,23 @@ func (v *P2PVPN) listenPacketConn() (c net.PacketConn, err error) {
return p2p.ListenPacket(peermap, p2pOptions...)
}
func (v *P2PVPN) addPeer(pi peer.ID, m peer.Metadata) {
v.RoutingTable.AddPeer(m.Alias1, m.Alias2, pi)
allowedIPs := m.Extra["allowedIPs"]
func (v *P2PVPN) addPeer(pi peer.ID, m url.Values) {
alias1 := m.Get("alias1")
alias2 := m.Get("alias2")
v.RoutingTable.AddPeer(alias1, alias2, pi)
allowedIPs := m["allowedIP"]
if allowedIPs == nil {
return
}
for _, allowIP := range allowedIPs.([]any) {
_, cidr, err := net.ParseCIDR(allowIP.(string))
for _, allowIP := range allowedIPs {
_, cidr, err := net.ParseCIDR(allowIP)
if err != nil {
continue
}
if cidr.IP.To4() != nil {
v.RoutingTable.AddRoute4(cidr, m.Alias1, v.Config.TunName)
v.RoutingTable.AddRoute4(cidr, alias1, v.Config.TunName)
} else {
v.RoutingTable.AddRoute6(cidr, m.Alias2, v.Config.TunName)
v.RoutingTable.AddRoute6(cidr, alias2, v.Config.TunName)
}
}
}

View File

@ -4,6 +4,7 @@ import (
"errors"
"log/slog"
"net"
"net/url"
"slices"
"sync"
"time"
@ -221,7 +222,7 @@ func (d *Datagram) TryEncrypt(symmAlgo secure.SymmAlgo) []byte {
type PeerFindEvent struct {
PeerID peer.ID
Metadata peer.Metadata
Metadata url.Values
}
type PeerUDPAddrEvent struct {

View File

@ -29,7 +29,7 @@ type WSConn struct {
*websocket.Conn
peermap *peermap.Peermap
peerID peer.ID
metadata peer.Metadata
metadata url.Values
closedSig chan int
datagrams chan *Datagram
peers chan *PeerFindEvent
@ -139,7 +139,7 @@ func (c *WSConn) dial(server string) error {
handshake.Set("X-Network", networkSecret.Secret)
handshake.Set("X-PeerID", c.peerID.String())
handshake.Set("X-Nonce", peer.NewNonce())
handshake.Set("X-Metadata", base64.StdEncoding.EncodeToString(c.metadata.MustMarshalJSON()))
handshake.Set("X-Metadata", c.metadata.Encode())
if server == "" {
server = c.peermap.String()
}
@ -291,10 +291,11 @@ func (c *WSConn) handleEvents(b []byte) {
Data: b[b[1]+2:],
}
case peer.CONTROL_NEW_PEER:
meta, _ := url.ParseQuery(string(b[b[1]+2:]))
event := PeerFindEvent{
PeerID: peer.ID(b[2 : b[1]+2]),
PeerID: peer.ID(b[2 : b[1]+2]),
Metadata: meta,
}
json.Unmarshal(b[b[1]+2:], &event.Metadata)
c.peers <- &event
case peer.CONTROL_NEW_PEER_UDP_ADDR:
addr, err := net.ResolveUDPAddr("udp", string(b[b[1]+2:]))
@ -346,7 +347,7 @@ func (c *WSConn) updateNetworkSecret(secret peer.NetworkSecret) {
slog.Error("NetworkSecretUpdate give up", "secret", secret)
}
func DialPeermap(peermap *peermap.Peermap, peerID peer.ID, metadata peer.Metadata) (*WSConn, error) {
func DialPeermap(peermap *peermap.Peermap, peerID peer.ID, metadata url.Values) (*WSConn, error) {
wsConn := &WSConn{
peermap: peermap,
peerID: peerID,

View File

@ -2,6 +2,7 @@ package p2p
import (
"errors"
"net/url"
"time"
"github.com/rkonfj/peerguard/peer"
@ -21,13 +22,13 @@ type Config struct {
DisableIPv6 bool
DisableIPv4 bool
SymmAlgo secure.SymmAlgo
Metadata peer.Metadata
Metadata url.Values
OnPeer OnPeer
KeepAlivePeriod time.Duration
}
type Option func(cfg *Config) error
type OnPeer func(peer.ID, peer.Metadata)
type OnPeer func(peer.ID, url.Values)
var (
OptionNoOp Option = func(cfg *Config) error { return nil }
@ -107,31 +108,40 @@ func FileSecretStore(storeFilePath string) peer.SecretStore {
func PeerSilenceMode() Option {
return func(cfg *Config) error {
cfg.Metadata.SilenceMode = true
if cfg.Metadata == nil {
cfg.Metadata = url.Values{}
}
cfg.Metadata.Set("silenceMode", "")
return nil
}
}
func PeerAlias1(alias string) Option {
return func(cfg *Config) error {
cfg.Metadata.Alias1 = alias
if cfg.Metadata == nil {
cfg.Metadata = url.Values{}
}
cfg.Metadata.Set("alias1", alias)
return nil
}
}
func PeerAlias2(alias string) Option {
return func(cfg *Config) error {
cfg.Metadata.Alias2 = alias
if cfg.Metadata == nil {
cfg.Metadata = url.Values{}
}
cfg.Metadata.Set("alias2", alias)
return nil
}
}
func PeerMeta(key string, value any) Option {
func PeerMeta(key string, value string) Option {
return func(cfg *Config) error {
if cfg.Metadata.Extra == nil {
cfg.Metadata.Extra = make(map[string]any)
if cfg.Metadata == nil {
cfg.Metadata = url.Values{}
}
cfg.Metadata.Extra[key] = value
cfg.Metadata.Add(key, value)
return nil
}
}

View File

@ -87,15 +87,3 @@ func (id ID) Len() byte {
func (id ID) Bytes() []byte {
return []byte(id)
}
type Metadata struct {
SilenceMode bool `json:"silenceMode"`
Alias1 string `json:"alias1"`
Alias2 string `json:"alias2"`
Extra map[string]any `json:"extra"`
}
func (meta Metadata) MustMarshalJSON() []byte {
b, _ := json.Marshal(meta)
return b
}

View File

@ -37,7 +37,7 @@ type Peer struct {
networkSecret auth.JSONSecret
networkContext *networkContext
metadata peer.Metadata
metadata url.Values
activeTime time.Time
id peer.ID
nonce byte
@ -117,17 +117,10 @@ func (p *Peer) Close() error {
}
func (p *Peer) String() string {
metadata := url.Values{}
metadata.Add("alias1", p.metadata.Alias1)
metadata.Add("alias2", p.metadata.Alias2)
for k, v := range p.metadata.Extra {
b, _ := json.Marshal(v)
metadata.Add(k, string(b))
}
return (&url.URL{
Scheme: "pg",
Host: string(p.id),
RawQuery: metadata.Encode(),
RawQuery: p.metadata.Encode(),
}).String()
}
@ -135,7 +128,7 @@ func (p *Peer) Start() {
p.activeTime = time.Now()
go p.readMessageLoop()
go p.keepalive()
if p.metadata.SilenceMode {
if p.metadata.Has("silenceMode") {
return
}
@ -149,7 +142,7 @@ func (p *Peer) Start() {
continue
}
if target.Val.metadata.SilenceMode {
if target.Val.metadata.Has("silenceMode") {
continue
}
p.leadDisco(target.Val)
@ -157,7 +150,7 @@ func (p *Peer) Start() {
}
func (p *Peer) leadDisco(target *Peer) {
myMeta := p.metadata.MustMarshalJSON()
myMeta := []byte(p.metadata.Encode())
b := make([]byte, 2+len(p.id)+len(myMeta))
b[0] = peer.CONTROL_NEW_PEER
b[1] = p.id.Len()
@ -165,7 +158,7 @@ func (p *Peer) leadDisco(target *Peer) {
copy(b[len(p.id)+2:], myMeta)
target.write(b)
peerMeta := target.metadata.MustMarshalJSON()
peerMeta := []byte(target.metadata.Encode())
b1 := make([]byte, 2+len(target.id)+len(peerMeta))
b1[0] = peer.CONTROL_NEW_PEER
b1[1] = target.id.Len()
@ -296,7 +289,7 @@ func (pm *PeerMap) GetPeer(network string, peerID peer.ID) (*Peer, error) {
return nil, fmt.Errorf("peer(%s/%s) not found", network, peerID)
}
func (pm *PeerMap) FindPeer(network string, filter func(peer.Metadata) bool) ([]*Peer, error) {
func (pm *PeerMap) FindPeer(network string, filter func(url.Values) bool) ([]*Peer, error) {
if ctx, ok := pm.networkMap.Get(network); ok {
var ret []*Peer
for item := range ctx.IterBuffered() {
@ -436,18 +429,22 @@ func (pm *PeerMap) HandlePeerPacketConnect(w http.ResponseWriter, r *http.Reques
networkContext: networkCtx,
id: peer.ID(peerID),
nonce: nonce,
metadata: peer.Metadata{},
connData: make(chan []byte, 128),
}
metadata := r.Header.Get("X-Metadata")
if len(metadata) > 0 {
b, err := base64.StdEncoding.DecodeString(metadata)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
_, err := base64.StdEncoding.DecodeString(metadata)
if err == nil {
w.WriteHeader(http.StatusForbidden)
return
}
json.Unmarshal(b, &peer.metadata)
meta, err := url.ParseQuery(metadata)
if err != nil {
w.WriteHeader(http.StatusForbidden)
return
}
peer.metadata = meta
}
if ok := networkCtx.SetIfAbsent(peerID, &peer); !ok {