package peer import ( "log" "net/netip" "sync/atomic" "time" ) // TODO: Remove func newRemotePeer(ip byte) *remotePeer { counter := uint64(time.Now().Unix()<<30 + 1) return &remotePeer{ IP: ip, counter: &counter, dupCheck: newDupCheck(0), } } // ---------------------------------------------------------------------------- type remotePeer struct { localIP byte IP byte // VPN IP of peer (last byte). Up bool // True if data can be sent on the peer. Relay bool // True if the peer is a relay. Direct bool // True if this is a direct connection. DirectAddr netip.AddrPort // Remote address if directly connected. PubSignKey []byte ControlCipher *controlCipher DataCipher *dataCipher counter *uint64 // For sending to. Atomic access only. dupCheck *dupCheck // For receiving from. Not safe for concurrent use. } func (p remotePeer) EncryptDataPacket(destIP byte, data, out []byte) []byte { h := header{ StreamID: dataStreamID, Counter: atomic.AddUint64(p.counter, 1), SourceIP: p.localIP, DestIP: destIP, } return p.DataCipher.Encrypt(h, data, out) } // Decrypts and de-dups incoming data packets. func (p remotePeer) DecryptDataPacket(h header, enc, out []byte) ([]byte, error) { dec, ok := p.DataCipher.Decrypt(enc, out) if !ok { return nil, errDecryptionFailed } if p.dupCheck.IsDup(h.Counter) { return nil, errDuplicateSeqNum } return dec, nil } // Peer must have a ControlCipher. func (p remotePeer) EncryptControlPacket(pkt marshaller, tmp, out []byte) []byte { tmp = pkt.Marshal(tmp) h := header{ StreamID: controlStreamID, Counter: atomic.AddUint64(p.counter, 1), SourceIP: p.localIP, DestIP: p.IP, } log.Printf("Encrypting with header: %#v", h) return p.ControlCipher.Encrypt(h, tmp, out) } // Returns a controlMsg[PacketType]. Peer must have a non-nil ControlCipher. // // This function also drops packets with duplicate sequence numbers. func (p remotePeer) DecryptControlPacket(fromAddr netip.AddrPort, h header, enc, tmp []byte) (any, error) { out, ok := p.ControlCipher.Decrypt(enc, tmp) if !ok { return nil, errDecryptionFailed } if p.dupCheck.IsDup(h.Counter) { return nil, errDuplicateSeqNum } msg, err := parseControlMsg(h.SourceIP, fromAddr, out) if err != nil { return nil, err } return msg, nil } // ---------------------------------------------------------------------------- type routingTable struct { // The LocalIP is the configured IP address of the local peer on the VPN. // // This value is constant. LocalIP byte // The LocalAddr is the configured local public address of the peer on the // internet. If LocalAddr.IsValid(), then the local peer has a public // address. // // This value is constant. LocalAddr netip.AddrPort // The remote peer configurations. These are updated by Peers [256]remotePeer // The current relay's VPN IP address, or zero if no relay is available. RelayIP byte } func newRoutingTable(localIP byte, localAddr netip.AddrPort) routingTable { rt := routingTable{ LocalIP: localIP, LocalAddr: localAddr, } for i := range rt.Peers { counter := uint64(time.Now().Unix()<<30 + 1) rt.Peers[i] = remotePeer{ localIP: localIP, IP: byte(i), counter: &counter, dupCheck: newDupCheck(0), } } return rt } func (rt *routingTable) GetRelay() (remotePeer, bool) { relay := rt.Peers[rt.RelayIP] return relay, relay.Up && relay.Direct }