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 }