func (sleeve *SleeveOverlay) handleFrame(sender *net.UDPAddr, fwd *sleeveForwarder, src []byte, dst []byte, frame []byte, dec *EthernetDecoder) { dec.DecodeLayers(frame) decodedLen := len(dec.decoded) if decodedLen == 0 { return } srcPeer := sleeve.peers.Fetch(mesh.PeerNameFromBin(src)) dstPeer := sleeve.peers.Fetch(mesh.PeerNameFromBin(dst)) if srcPeer == nil || dstPeer == nil { return } // Handle special frames produced internally (rather than // captured/forwarded) by the remote router. // // We really shouldn't be decoding these above, since they are // not genuine Ethernet frames. However, it is actually more // efficient to do so, as we want to optimise for the common // (i.e. non-special) frames. These always need decoding, and // detecting special frames is cheaper post decoding than pre. if decodedLen == 1 && dec.IsSpecial() { if srcPeer == fwd.remotePeer && dstPeer == fwd.sleeve.localPeer { select { case fwd.specialChan <- specialFrame{sender, frame}: case <-fwd.finishedChan: } } return } sleeve.sendToConsumer(srcPeer, dstPeer, frame, dec) }
func (sleeve *SleeveOverlay) readUDP() { defer sleeve.conn.Close() dec := NewEthernetDecoder() buf := make([]byte, MaxUDPPacketSize) for { n, sender, err := sleeve.conn.ReadFromUDP(buf) if err == io.EOF { return } else if err != nil { log.Print("ignoring UDP read error ", err) continue } else if n < NameSize { log.Print("ignoring too short UDP packet from ", sender) continue } fwdName := mesh.PeerNameFromBin(buf[:NameSize]) fwd := sleeve.lookupForwarder(fwdName) if fwd == nil { continue } packet := make([]byte, n-NameSize) copy(packet, buf[NameSize:n]) err = fwd.crypto.Dec.IterateFrames(packet, func(src []byte, dst []byte, frame []byte) { sleeve.handleFrame(sender, fwd, src, dst, frame, dec) }) if err != nil { // Errors during UDP packet decoding / // processing are non-fatal. One common cause // is that we receive and attempt to decrypt a // "stray" packet. This can actually happen // quite easily if there is some connection // churn between two peers. After all, UDP // isn't a connection-oriented protocol, yet // we pretend it is. // // If anything really is seriously, // unrecoverably amiss with a connection, that // will typically result in missed heartbeats // and the connection getting shut down // because of that. log.Print(fwd.logPrefixFor(sender), err) } } }