package peer import ( "log" "net/netip" "sync" ) // ---------------------------------------------------------------------------- type connWriter struct { localIP byte conn udpWriter // For sending control packets. cBuf1 []byte cBuf2 []byte // For sending data packets. dBuf1 []byte dBuf2 []byte // Lock around for sending on UDP Conn. wLock sync.Mutex } func newConnWriter(conn udpWriter, localIP byte) *connWriter { w := &connWriter{ localIP: localIP, conn: conn, cBuf1: make([]byte, bufferSize), cBuf2: make([]byte, bufferSize), dBuf1: make([]byte, bufferSize), dBuf2: make([]byte, bufferSize), } return w } // Not safe for concurrent use. Should only be called by supervisor. func (w *connWriter) SendControlPacket(pkt marshaller, route *peerRoute) { enc := encryptControlPacket(w.localIP, route, pkt, w.cBuf1, w.cBuf2) w.writeTo(enc, route.RemoteAddr) } // Relay control packet. Route must not be nil. func (w *connWriter) RelayControlPacket(pkt marshaller, route, relay *peerRoute) { enc := encryptControlPacket(w.localIP, route, pkt, w.cBuf1, w.cBuf2) enc = encryptDataPacket(w.localIP, route.IP, relay, enc, w.cBuf1) w.writeTo(enc, relay.RemoteAddr) } // Not safe for concurrent use. Should only be called by ifReader. func (w *connWriter) SendDataPacket(pkt []byte, route *peerRoute) { enc := encryptDataPacket(w.localIP, route.IP, route, pkt, w.dBuf1) w.writeTo(enc, route.RemoteAddr) } // Relay a data packet. Route must not be nil. func (w *connWriter) RelayDataPacket(pkt []byte, route, relay *peerRoute) { enc := encryptDataPacket(w.localIP, route.IP, route, pkt, w.dBuf1) enc = encryptDataPacket(w.localIP, route.IP, relay, enc, w.dBuf2) w.writeTo(enc, relay.RemoteAddr) } // Safe for concurrent use. Should only be called by connReader. // // This function will send pkt to the peer directly. This is used when a peer // is acting as a relay and is forwarding already encrypted data for another // peer. func (w *connWriter) SendEncryptedDataPacket(pkt []byte, route *peerRoute) { w.writeTo(pkt, route.RemoteAddr) } func (w *connWriter) writeTo(packet []byte, addr netip.AddrPort) { w.wLock.Lock() if _, err := w.conn.WriteToUDPAddrPort(packet, addr); err != nil { log.Printf("[ConnWriter] Failed to write to UDP port: %v", err) } w.wLock.Unlock() }