// Reads datagrams from the connection and queues them for processing on the // l-goroutine. func (dht *DHT) readLoop() { for { b, addr, err := denet.ReadDatagramFromUDP(dht.conn) switch { // Successful receive. case err == nil: dht.rxChan <- packet{ Data: b, Addr: *addr, } // An address was unreachable. case denet.ErrorIsPortUnreachable(err): dht.addrUnreachableChan <- *addr // Unless we are stopping, other errors should not occur. case atomic.LoadUint32(&dht.stopping) == 0: log.Errore(err, "unexpected error while receiving") // We are stopping. default: return } } }
func (d *DHT) sendMsg(conn *net.UDPConn, raddr net.UDPAddr, query interface{}) error { err := sendMsg(conn, raddr, query) if err != nil && denet.ErrorIsPortUnreachable(err) { d.processUnreachable(raddr) } return err }
func (dht *DHT) lTxQuery(n *node, method string, args interface{}) error { q, err := krpc.MakeQuery(method, args) if err != nil { return err } n.PendingQueries[q.TxID] = q err = krpc.Write(dht.conn, n.Addr, q) if err != nil && denet.ErrorIsPortUnreachable(err) { dht.lNodeUnreachable(n) } return nil }
// sendMsg bencodes the data in 'query' and sends it to the remote node. func sendMsg(conn *net.UDPConn, raddr net.UDPAddr, query interface{}) error { totalSent.Add(1) var b bytes.Buffer if err := bencode.Marshal(&b, query); err != nil { return err } if n, err := conn.WriteToUDP(b.Bytes(), &raddr); err != nil { if denet.ErrorIsPortUnreachable(err) { fmt.Println("DHT: port unreachable: ", err) return err } // all other errors are quashed //fmt.Println("DHT: node write failed:", err) } else { totalWrittenBytes.Add(int64(n)) } return nil }
// Read from UDP socket, writes slice of byte into channel. func readFromSocket(socket *net.UDPConn, conChan chan packetType, unrChan chan net.UDPAddr, bytesArena arena, stop chan bool) { for { b := bytesArena.Pop() n, addr, err := socket.ReadFromUDP(b) b = b[0:n] if n == maxUDPPacketSize { // debug.Printf("DHT: Warning. Received packet with len >= %d, some data may have been discarded.\n", maxUDPPacketSize) } totalReadBytes.Add(int64(n)) if n > 0 && err == nil { p := packetType{b, *addr} select { case conChan <- p: continue case <-stop: return } } if err != nil && denet.ErrorIsPortUnreachable(err) && addr != nil { fmt.Println("Marking unreachable: ", addr.String()) unrChan <- *addr } // debug.Println("DHT: readResponse error:", err) // Do a non-blocking read of the stop channel and stop this goroutine if the channel // has been closed. select { case <-stop: return default: } } }