package peer import ( "io" "log" "sync/atomic" ) type ifReader struct { iface io.Reader routes [256]*atomic.Pointer[peerRoute] relay *atomic.Pointer[peerRoute] sender dataPacketSender } func newIFReader( iface io.Reader, routes [256]*atomic.Pointer[peerRoute], relay *atomic.Pointer[peerRoute], sender dataPacketSender, ) *ifReader { return &ifReader{ iface: iface, routes: routes, relay: relay, sender: sender, } } func (r *ifReader) Run() { var ( packet = make([]byte, bufferSize) remoteIP byte ok bool ) for { packet = r.readNextPacket(packet) if remoteIP, ok = r.parsePacket(packet); ok { r.sendPacket(packet, remoteIP) } } } func (r *ifReader) sendPacket(pkt []byte, remoteIP byte) { route := r.routes[remoteIP].Load() if !route.Up { log.Printf("Route not connected: %d", remoteIP) return } // Direct path => early return. if route.Direct { r.sender.SendDataPacket(pkt, route) return } if relay := r.relay.Load(); relay != nil && relay.Up { r.sender.RelayDataPacket(pkt, route, relay) } } // Get next packet, returning packet, and destination ip. func (r *ifReader) readNextPacket(buf []byte) []byte { n, err := r.iface.Read(buf[:cap(buf)]) if err != nil { log.Fatalf("Failed to read from interface: %v", err) } return buf[:n] } func (r *ifReader) parsePacket(buf []byte) (byte, bool) { n := len(buf) if n == 0 { return 0, false } version := buf[0] >> 4 switch version { case 4: if n < 20 { log.Printf("Short IPv4 packet: %d", len(buf)) return 0, false } return buf[19], true case 6: if len(buf) < 40 { log.Printf("Short IPv6 packet: %d", len(buf)) return 0, false } return buf[39], true default: log.Printf("Invalid IP packet version: %v", version) return 0, false } }