github.com/status-im/status-go@v1.1.0/server/pairing/peers/udp_notifier.go (about)

     1  package peers
     2  
     3  import (
     4  	"crypto/rand"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/golang/protobuf/proto"
     9  	udpp2p "github.com/schollz/peerdiscovery"
    10  	"go.uber.org/zap"
    11  )
    12  
    13  const (
    14  	pingInterval = 500 * time.Millisecond
    15  	searchLimit  = 2 * time.Minute
    16  )
    17  
    18  type NotifyHandler func(*LocalPairingPeerHello)
    19  
    20  type UDPNotifier struct {
    21  	logger       *zap.Logger
    22  	id           []byte
    23  	notifyOutput NotifyHandler
    24  }
    25  
    26  func NewUDPNotifier(logger *zap.Logger, outputFunc NotifyHandler) (*UDPNotifier, error) {
    27  	randID := make([]byte, 32)
    28  	_, err := rand.Read(randID)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  
    33  	n := new(UDPNotifier)
    34  	n.logger = logger
    35  	n.id = randID
    36  	n.notifyOutput = outputFunc
    37  	return n, nil
    38  }
    39  
    40  func (u *UDPNotifier) makePayload(deviceName, deviceType string) (*LocalPairingPeerHello, error) {
    41  	return NewLocalPairingPeerHello(u.id, deviceName, deviceType, k)
    42  }
    43  
    44  func (u *UDPNotifier) notify(d udpp2p.Discovered) {
    45  	h := new(LocalPairingPeerHello)
    46  	err := proto.Unmarshal(d.Payload, &h.LocalPairingPeerHello)
    47  	if err != nil {
    48  		u.logger.Error("notify unmarshalling of payload failed", zap.Error(err))
    49  		return
    50  	}
    51  
    52  	ok := h.verify(&k.PublicKey)
    53  	if !ok {
    54  		u.logger.Error("verification of unmarshalled payload failed", zap.Any("LocalPairingPeerHello", h))
    55  		return
    56  	}
    57  
    58  	h.Discovered = d
    59  	u.notifyOutput(h)
    60  }
    61  
    62  func (u *UDPNotifier) MakeUDPP2PSettings(deviceName, deviceType string) (*udpp2p.Settings, error) {
    63  	if u.notifyOutput == nil {
    64  		return nil, fmt.Errorf("UDPNotifier has no notiftOutput function defined")
    65  	}
    66  
    67  	h, err := u.makePayload(deviceName, deviceType)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	mh, err := proto.Marshal(&h.LocalPairingPeerHello)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	return &udpp2p.Settings{
    78  		Notify:  u.notify,
    79  		Payload: mh,
    80  	}, nil
    81  }
    82  
    83  func Search(deviceName, deviceType string, notify NotifyHandler, stop chan struct{}, logger *zap.Logger) error {
    84  	un, err := NewUDPNotifier(logger, notify)
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	settings, err := un.MakeUDPP2PSettings(deviceName, deviceType)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	settings.Delay = pingInterval
    95  	settings.TimeLimit = searchLimit
    96  	settings.StopChan = stop
    97  
    98  	go func() {
    99  		_, err = udpp2p.Discover(*settings)
   100  		logger.Error("error while discovering udp peers", zap.Error(err))
   101  	}()
   102  	return nil
   103  }