github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/p2p/common.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package p2p
    19  
    20  import (
    21  	"context"
    22  	"errors"
    23  	"fmt"
    24  	"net"
    25  	"net/url"
    26  
    27  	"google.golang.org/protobuf/proto"
    28  
    29  	"github.com/mysteriumnetwork/node/communication/nats"
    30  	"github.com/mysteriumnetwork/node/core/port"
    31  	"github.com/mysteriumnetwork/node/identity"
    32  	"github.com/mysteriumnetwork/node/pb"
    33  )
    34  
    35  const (
    36  	requiredConnCount  = 2
    37  	consumerInitialTTL = 128
    38  )
    39  
    40  type brokerConnector interface {
    41  	Connect(serverURIs ...*url.URL) (nats.Connection, error)
    42  }
    43  
    44  type natConsumerPinger interface {
    45  	PingProviderPeer(ctx context.Context, localIP, remoteIP string, localPorts, remotePorts []int, initialTTL int, n int) (conns []*net.UDPConn, err error)
    46  }
    47  
    48  type natProviderPinger interface {
    49  	PingConsumerPeer(ctx context.Context, id string, ip string, localPorts, remotePorts []int, initialTTL int, n int) (conns []*net.UDPConn, err error)
    50  }
    51  
    52  func configExchangeSubject(providerID identity.Identity, serviceType string) string {
    53  	return fmt.Sprintf("%s.%s.p2p-config-exchange", providerID.Address, serviceType)
    54  }
    55  
    56  func configExchangeACKSubject(providerID identity.Identity, serviceType string) string {
    57  	return fmt.Sprintf("%s.%s.p2p-config-exchange-ack", providerID.Address, serviceType)
    58  }
    59  
    60  func channelHandlersReadySubject(providerID identity.Identity, serviceType string) string {
    61  	return fmt.Sprintf("%s.%s.p2p-channel-handlers-ready", providerID.Address, serviceType)
    62  }
    63  
    64  func acquireLocalPorts(portPool port.ServicePortSupplier, n int) ([]int, error) {
    65  	ports, err := portPool.AcquireMultiple(n)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	var res []int
    70  	for _, p := range ports {
    71  		res = append(res, p.Num())
    72  	}
    73  	return res, nil
    74  }
    75  
    76  // packSignedMsg marshals, signs and returns ready to send bytes.
    77  func packSignedMsg(signer identity.SignerFactory, signerID identity.Identity, msg *pb.P2PConfigExchangeMsg) ([]byte, error) {
    78  	protoBytes, err := proto.Marshal(msg)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	signature, err := signer(signerID).Sign(protoBytes)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	signedMsg := &pb.P2PSignedMsg{Data: protoBytes, Signature: signature.Bytes()}
    87  	signedMsgProtoBytes, err := proto.Marshal(signedMsg)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	return signedMsgProtoBytes, nil
    92  }
    93  
    94  // unpackSignedMsg verifies and unmarshal bytes to signed message.
    95  func unpackSignedMsg(verifier identity.Verifier, b []byte) (*pb.P2PSignedMsg, identity.Identity, error) {
    96  	var signedMsg pb.P2PSignedMsg
    97  	if err := proto.Unmarshal(b, &signedMsg); err != nil {
    98  		return nil, identity.Identity{}, err
    99  	}
   100  	ok, id := verifier.Verify(signedMsg.Data, identity.SignatureBytes(signedMsg.Signature))
   101  	if !ok {
   102  		return nil, id, errors.New("message signature is invalid")
   103  	}
   104  	return &signedMsg, id, nil
   105  }
   106  
   107  // encryptConnConfigMsg encrypts proto message and returns bytes.
   108  func encryptConnConfigMsg(msg *pb.P2PConnectConfig, privateKey PrivateKey, peerPubKey PublicKey) ([]byte, error) {
   109  	protoBytes, err := proto.Marshal(msg)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	ciphertext, err := privateKey.Encrypt(peerPubKey, protoBytes)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	return ciphertext, nil
   118  }
   119  
   120  // decryptConnConfigMsg decrypts bytes to connect config.
   121  func decryptConnConfigMsg(ciphertext []byte, privateKey PrivateKey, peerPubKey PublicKey) (*pb.P2PConnectConfig, error) {
   122  	peerConnectConfigProtoBytes, err := privateKey.Decrypt(peerPubKey, ciphertext)
   123  	if err != nil {
   124  		return nil, fmt.Errorf("could not decrypt config to proto bytes: %w", err)
   125  	}
   126  	var peerProtoConnectConfig pb.P2PConnectConfig
   127  	if err := proto.Unmarshal(peerConnectConfigProtoBytes, &peerProtoConnectConfig); err != nil {
   128  		return nil, fmt.Errorf("could not unmarshal decrypted conn config: %w", err)
   129  	}
   130  	return &peerProtoConnectConfig, nil
   131  }
   132  
   133  func int32ToIntSlice(arr []int32) []int {
   134  	var res []int
   135  	for _, v := range arr {
   136  		res = append(res, int(v))
   137  	}
   138  	return res
   139  }
   140  
   141  func intToInt32Slice(arr []int) []int32 {
   142  	var res []int32
   143  	for _, v := range arr {
   144  		res = append(res, int32(v))
   145  	}
   146  	return res
   147  }