Files
pg/p2p/config.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)
}