mirror of
https://github.com/sigcn/pg.git
synced 2025-10-05 02:46:51 +08:00
180 lines
3.6 KiB
Go
180 lines
3.6 KiB
Go
package p2p
|
|
|
|
import (
|
|
"crypto/ecdh"
|
|
"crypto/rand"
|
|
"errors"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/sigcn/pg/disco"
|
|
"github.com/sigcn/pg/secure"
|
|
"github.com/sigcn/pg/secure/chacha20poly1305"
|
|
"storj.io/common/base58"
|
|
)
|
|
|
|
var defaultSymmAlgo func(secure.ProvideSecretKey) secure.SymmAlgo = chacha20poly1305.New
|
|
|
|
func SetDefaultSymmAlgo(symmAlgo func(secure.ProvideSecretKey) secure.SymmAlgo) {
|
|
defaultSymmAlgo = symmAlgo
|
|
}
|
|
|
|
type Config struct {
|
|
UDPPort int
|
|
DisableIPv6 bool
|
|
DisableIPv4 bool
|
|
PeerInfo disco.Peer
|
|
SymmAlgo secure.SymmAlgo
|
|
OnPeer OnPeer
|
|
OnPeerLeave OnPeerLeave
|
|
KeepAlivePeriod time.Duration
|
|
MinDiscoPeriod time.Duration
|
|
}
|
|
|
|
type Option func(cfg *Config) error
|
|
type OnPeer func(disco.PeerID, url.Values)
|
|
type OnPeerLeave func(disco.PeerID)
|
|
|
|
var (
|
|
OptionNoOp Option = func(cfg *Config) error { return nil }
|
|
)
|
|
|
|
func ListenUDPPort(port int) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.UDPPort = port
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func ListenPeerID(id string) Option {
|
|
return func(cfg *Config) error {
|
|
if cfg.SymmAlgo != nil {
|
|
return errors.New("options ListenPeerID and ListenPeerSecure/Curve25519 conflict")
|
|
}
|
|
peerID := disco.PeerID(id)
|
|
if peerID.Len() > 0 {
|
|
cfg.PeerInfo.ID = peerID
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func ListenPeerSecure() Option {
|
|
return func(cfg *Config) error {
|
|
priv, err := ecdh.X25519().GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ListenPeerCurve25519(base58.Encode(priv.Bytes()))(cfg)
|
|
}
|
|
}
|
|
|
|
func ListenPeerCurve25519(privateKey string) Option {
|
|
return func(cfg *Config) error {
|
|
if cfg.SymmAlgo != nil {
|
|
return errors.New("repeat secure options")
|
|
}
|
|
curve := ecdh.X25519()
|
|
priv, err := curve.NewPrivateKey(base58.Decode(privateKey))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cfg.SymmAlgo = defaultSymmAlgo(func(pubKey string) ([]byte, error) {
|
|
pub, err := curve.NewPublicKey(base58.Decode(pubKey))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return priv.ECDH(pub)
|
|
})
|
|
cfg.PeerInfo.ID = disco.PeerID(base58.Encode(priv.PublicKey().Bytes()))
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func ListenIPv6Only() Option {
|
|
return func(cfg *Config) error {
|
|
cfg.DisableIPv4 = true
|
|
cfg.DisableIPv6 = false
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func ListenIPv4Only() Option {
|
|
return func(cfg *Config) error {
|
|
cfg.DisableIPv4 = false
|
|
cfg.DisableIPv6 = true
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func ListenPeerUp(onPeer OnPeer) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.OnPeer = onPeer
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func ListenPeerLeave(onPeerLeave OnPeerLeave) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.OnPeerLeave = onPeerLeave
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func PeerSilenceMode() Option {
|
|
return func(cfg *Config) error {
|
|
cfg.PeerInfo.WithSilenceMode()
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func PeerAlias1(alias string) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.PeerInfo.WithMeta("alias1", alias)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func PeerAlias2(alias string) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.PeerInfo.WithMeta("alias2", alias)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func PeerMeta(key string, value string) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.PeerInfo.WithMeta(key, value)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func KeepAlivePeriod(period time.Duration) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.KeepAlivePeriod = period
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func MinDiscoPeriod(period time.Duration) Option {
|
|
return func(cfg *Config) error {
|
|
cfg.MinDiscoPeriod = period
|
|
return nil
|
|
}
|
|
}
|
|
|
|
type TransportMode string
|
|
|
|
const (
|
|
MODE_DEFAULT TransportMode = ""
|
|
MODE_FORCE_PEER_RELAY TransportMode = "PEER_RELAY"
|
|
MODE_FORCE_RELAY TransportMode = "RELAY"
|
|
)
|
|
|
|
func (mode TransportMode) String() string {
|
|
if mode == "" {
|
|
return "DEFAULT"
|
|
}
|
|
return string(mode)
|
|
}
|