func receiveUDP(udpConn *net.UDPConn, rAddr *net.UDPAddr) { b := make([]byte, 1024) udpConn.SetReadDeadline(time.Now().Add(5 * time.Second)) n, Addr, err := udpConn.ReadFromUDP(b) // n,err:=udpConn.Read(b) if err != nil { fmt.Println(err.Error()) return } if n > 1024 { fmt.Println("Buff out!") return } fmt.Println(udpConn.RemoteAddr().Network()) if !Addr.IP.Equal(rAddr.IP) { fmt.Println("IP diff:%s-%s", Addr.IP.String(), rAddr.IP.String()) return } else if Addr.Port != rAddr.Port { fmt.Println("Port diff:%d-%d", Addr.Port, rAddr.Port) return } fmt.Printf("Receive from %s:%s", udpConn.RemoteAddr().String(), b[:n]) }
// HandleFind - Receives a Find message with a list of peers in this environment func (dht *DHTClient) HandleFind(data DHTMessage, conn *net.UDPConn) { // This means we've received a list of nodes we can connect to if data.Arguments != "" { ids := strings.Split(data.Arguments, ",") if len(ids) == 0 { Log(Error, "Malformed list of peers received") } else { // Go over list of received peer IDs and look if we know // anything about them. Add every new peer into list of peers for _, id := range ids { var found = false for _, peer := range dht.Peers { if peer.ID == id { found = true } } if !found { var p PeerIP p.ID = id dht.Peers = append(dht.Peers, p) } } k := 0 for _, peer := range dht.Peers { var found = false for _, id := range ids { if peer.ID == id { found = true } } if found { dht.Peers[k] = peer k++ } } dht.Peers = dht.Peers[:k] if dht.PeerChannel == nil { dht.PeerChannel = make(chan []PeerIP) } dht.PeerChannel <- dht.Peers Log(Debug, "Received peers from %s: %s", conn.RemoteAddr().String(), data.Arguments) dht.UpdateLastCatch(data.Arguments) } } else { dht.Peers = dht.Peers[:0] } }
func (p *Proxy) proxyUDPStream(ctx context.Context, src *net.UDPConn) { srcRemoteAddr := src.RemoteAddr().(*net.UDPAddr) srcLocalAddr := src.LocalAddr().(*net.UDPAddr) route := p.routes.GetTable().Lookup(protocols.UDP, srcRemoteAddr.IP, srcLocalAddr.IP, uint16(srcRemoteAddr.Port), uint16(srcLocalAddr.Port)) if route == nil { src.Close() return } go func() { dstAddr := net.UDPAddr{ IP: route.Outbound.DstIP, Port: int(route.Outbound.DstPort), } dst, err := net.DialUDP("udp", nil, &dstAddr) if err != nil { src.Close() return } dst.SetKeepAlivePeriod(10 * time.Second) src.SetKeepAlivePeriod(10 * time.Second) go func() { <-ctx.Done() src.Close() dst.Close() }() go func() { defer dst.CloseWrite() defer src.CloseRead() io.Copy(dst, src) }() go func() { defer src.CloseWrite() defer dst.CloseRead() io.Copy(src, dst) }() }() }
func readAndWriteUDP(r io.Reader, w io.Writer, con *net.UDPConn, ra net.Addr, verbose bool) <-chan net.Addr { buf := make([]byte, BUFFER_LIMIT) cAddr := make(chan net.Addr) go func() { defer func() { con.Close() cAddr <- ra }() for { var bytesread int var errRead, errWrite error if con, ok := r.(*net.UDPConn); ok { var addr net.Addr bytesread, addr, errRead = con.ReadFrom(buf) if con.RemoteAddr() == nil && ra == nil { ra = addr cAddr <- ra } } else { bytesread, errRead = r.Read(buf) } if errRead != nil { if errRead != io.EOF { if verbose { log.Println("READ ERROR: ", errRead) } } break } if con, ok := w.(*net.UDPConn); ok && con.RemoteAddr() == nil { _, errWrite = con.WriteTo(buf[0:bytesread], ra) } else { _, errWrite = w.Write(buf[0:bytesread]) } if errWrite != nil { if verbose { log.Println("WRITE ERROR: ", errWrite) } return } } }() return cAddr }
// HandleConn analyzes received connecting message and assigns received // cliend ID if any func (dht *DHTClient) HandleConn(data DHTMessage, conn *net.UDPConn) { if dht.State != DHTStateConnecting && dht.State != DHTStateReconnecting { return } if data.ID == "" { Log(Error, "Empty ID was received") return } if data.ID == "0" { Log(Error, "Empty ID were received. Stopping") return } dht.State = DHTStateOperating dht.ID = data.ID Log(Info, "Received connection confirmation from router %s", conn.RemoteAddr().String()) Log(Info, "Received personal ID for this session: %s", data.ID) }
func HandleUDPConnection(con *net.UDPConn, verbose bool) { chan_remote := readAndWriteUDP(con, os.Stdout, con, nil, verbose) ra := con.RemoteAddr() if ra == nil { ra = <-chan_remote } chan_local := readAndWriteUDP(os.Stdin, con, con, ra, verbose) select { case <-chan_local: if verbose { log.Println("Connection closed from local process") } case <-chan_remote: if verbose { log.Println("Connection closed from remote process") } } }
// ListenDHT - listens for packets received from DHT bootstrap node // Every packet is unmarshaled and turned into Request structure // which we should analyze and respond func (dht *DHTClient) ListenDHT(conn *net.UDPConn) { defer conn.Close() Log(Info, "Bootstraping via %s", conn.RemoteAddr().String()) dht.Listeners++ var failCounter = 0 for { if dht.Shutdown { Log(Info, "Closing DHT Connection to %s", conn.RemoteAddr().String()) conn.Close() for i, c := range dht.Connection { if c.RemoteAddr().String() == conn.RemoteAddr().String() { dht.Connection = append(dht.Connection[:i], dht.Connection[i+1:]...) } } break } var buf [512]byte _, _, err := conn.ReadFromUDP(buf[0:]) if err != nil { Log(Debug, "Failed to read from Discovery Service: %v", err) failCounter++ } else { failCounter = 0 data, err := dht.Extract(buf[:512]) if err != nil { Log(Error, "Failed to extract a message received from discovery service: %v", err) } else { callback, exists := dht.ResponseHandlers[data.Command] if exists { Log(Trace, "DHT Received %v", data) callback(data, conn) } else { Log(Debug, "Unsupported packet type received from DHT: %s", data.Command) } } } if failCounter > 1000 { Log(Error, "Multiple errors reading from DHT") break } } dht.Listeners-- }
func dnsReqResp(name string, conn *net.UDPConn) (net.IP, error) { //question var ret net.IP remote := conn.RemoteAddr().String() header, err := dnsQdGen(name, remote) if err != nil { return ret, qdGenError } _, err = conn.Write(header) if err != nil { return ret, reqNetworkError } respBuf := make([]byte, dnsBufSize) nread, _, err := conn.ReadFromUDP(respBuf[:dnsRespMax]) if err != nil { return ret, respNetworkError } //respose respRd := bytes.NewReader(respBuf) dns := dnsHeader{} err = binary.Read(respRd, binary.BigEndian, &dns) if (dns.Flags&_QR) == 0 || err != nil { return ret, respFormatError } numQd := dns.QdCount numAn := dns.AnCount buflen := len(respBuf) pos := int(unsafe.Sizeof(dns)) for i := 0; i < int(numQd); i++ { for { n := int(respBuf[pos]) if n == 0 { pos += 1 break } if n > nameLenMax { return ret, respFormatError } pos += (n + 1) if pos >= buflen { return ret, respFormatError } } pos += 4 //skip type and class } if pos >= nread { return ret, respFormatError } for i := 0; i < int(numAn); i++ { size := parseNameSize(respBuf, pos) if size <= 0 { return ret, respFormatError } pos += size tp := (respBuf[pos] << 16) + respBuf[pos+1] pos += 8 //skip type, class ttl if pos >= nread { return ret, respFormatError } dataLen := (respBuf[pos] << 16) + respBuf[pos+1] pos += 2 //skip data len if tp == qdTypeA && dataLen == net.IPv4len { ret = respBuf[pos : pos+4] return ret, nil } pos += int(dataLen) //skip data if pos >= nread { return ret, respFormatError } } return ret, respNotFoundError }
// Sends the data in sendbuf to peer_addr (with possible resends) and waits for // an ACK with the correct block id, if sendbuf contains a DATA message. // Returns true if the sending was successful and the ACK was received. func sendAndWaitForAck(udp_conn *net.UDPConn, peer_addr *net.UDPAddr, sendbuf []byte, retransmissions, dups, strays *int) bool { // absolute deadline when this function will return false deadline := time.Now().Add(total_timeout) readbuf := make([]byte, 4096) *retransmissions-- // to counter the ++ being done at the start of the loop outer: for { // re/send *retransmissions++ n, err := udp_conn.Write(sendbuf) if err != nil { util.Log(0, "ERROR! TFTP error in Write(): %v", err) break } if n != len(sendbuf) { util.Log(0, "ERROR! TFTP: Incomplete write") break } //util.Log(2, "DEBUG! TFTP: Sent %v bytes to %v. Waiting for ACK...", len(sendbuf), peer_addr) for { // check absolute deadline if time.Now().After(deadline) { break outer } // set deadline for next read timo := time.Duration(rand.Int63n(int64(max_wait_retry-min_wait_retry))) + min_wait_retry endtime2 := time.Now().Add(timo) if endtime2.After(deadline) { endtime2 = deadline } udp_conn.SetReadDeadline(endtime2) n, from, err := udp_conn.ReadFromUDP(readbuf) if err != nil { e, ok := err.(*net.OpError) if !ok || !e.Timeout() { util.Log(0, "ERROR! TFTP ReadFromUDP() failed while waiting for ACK from %v (local address: %v): %v", udp_conn.RemoteAddr(), udp_conn.LocalAddr(), err) break outer // retries make no sense => bail out } else { //util.Log(2, "DEBUG! TFTP timeout => resend %#v", sendbuf) continue outer // resend } } if from.Port != peer_addr.Port { *strays++ emsg := fmt.Sprintf("WARNING! TFTP server got UDP packet from incorrect source: %v instead of %v", from.Port, peer_addr.Port) sendError(udp_conn, from, 5, emsg) // 5 => Unknown transfer ID continue // This error is not fatal since it doesn't affect our peer } if n == 4 && readbuf[0] == 0 && readbuf[1] == 4 && // 4 => ACK (sendbuf[1] != 3 || // we did not send DATA // or the ACK's block id is the same as the one we sent (readbuf[2] == sendbuf[2] && readbuf[3] == sendbuf[3])) { //util.Log(2, "DEBUG! TFTP: Received ACK from %v: %#v", peer_addr, readbuf[0:n]) return true } else { if readbuf[0] == 0 && readbuf[1] == 5 { // error util.Log(0, "ERROR! TFTP ERROR received while waiting for ACK from %v: %v", peer_addr, string(readbuf[4:n])) break outer // retries make no sense => bail out } else { // if we sent DATA but the ACK is not for the block we sent, // increase dup counter. If we wanted to be anal we would need to check // if the block id is one less for it to be an actual dup, but // since the dup counter is only for reporting, we don't care. if sendbuf[1] == 3 && (readbuf[2] != sendbuf[2] || readbuf[3] != sendbuf[3]) { *dups++ //util.Log(2, "DEBUG! TFTP duplicate ACK received: %#v => Ignored", string(readbuf[0:n])) // ONLY "continue", NOT "continue outer", i.e. DUPs DO NOT CAUSE A RESEND. // THIS PREVENTS http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome // When timeout happens, it will cause a resend. continue } else { emsg := fmt.Sprintf("ERROR! TFTP server waiting for ACK from %v but got: %#v", peer_addr, string(readbuf[0:n])) sendError(udp_conn, from, 0, emsg) // 0 => Unspecified error break outer // retries make no sense => bail out } } } } } util.Log(0, "ERROR! TFTP send not acknowledged by %v (retransmissions: %v, dups: %v, strays: %v)", peer_addr, *retransmissions, *dups, *strays) return false }
func close(c *net.UDPConn) { log.Printf("closing: %s -> %s", c.LocalAddr().String(), c.RemoteAddr().String()) c.Close() }