func getReflexive(sock *net.UDPConn) (*net.UDPAddr, error) { serverAddr, err := net.ResolveUDPAddr("udp", *stunserver) if err != nil { return nil, errors.New("Couldn't resolve STUN server") } var tid [12]byte if _, err = rand.Read(tid[:]); err != nil { return nil, err } request, err := stun.BindRequest(tid[:], nil, true, false) if err != nil { return nil, err } n, err := sock.WriteTo(request, serverAddr) if err != nil { return nil, err } if n < len(request) { return nil, err } var buf [1024]byte n, _, err = sock.ReadFromUDP(buf[:]) if err != nil { return nil, err } packet, err := stun.ParsePacket(buf[:n], nil) if err != nil { return nil, err } if packet.Class != stun.ClassSuccess || packet.Method != stun.MethodBinding || packet.Addr == nil || !bytes.Equal(tid[:], packet.Tid[:]) { return nil, errors.New("No address provided by STUN server") } return packet.Addr, nil }
func (e *attemptEngine) xmit() (time.Time, error) { now := time.Now() var ret time.Time var err error for i := range e.attempts { if e.attempts[i].timeout.Before(now) { e.attempts[i].timeout = time.Now().Add(probeTimeout) e.attempts[i].tid, err = stun.RandomTid() if err != nil { return time.Time{}, err } packet, err := stun.BindRequest(e.attempts[i].tid, nil, false, e.attempts[i].chosen) if err != nil { return time.Time{}, err } e.sock.WriteToUDP(packet, e.attempts[i].Addr) } if ret.IsZero() || e.attempts[i].timeout.Before(ret) { ret = e.attempts[i].timeout } } return ret, nil }
func main() { flag.Parse() serverAddr, err := net.ResolveUDPAddr("udp", *server) if err != nil { fmt.Println("Couldn't resolve", *server) os.Exit(1) } tid := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc} request, err := stun.BindRequest(tid, nil, true, false) if err != nil { fmt.Println("Failed to build STUN request:", err) os.Exit(1) } sock, err := net.ListenUDP("udp", &net.UDPAddr{Port: *sourcePort}) if err != nil { fmt.Println("Couldn't listen on UDP port", *sourcePort) os.Exit(1) } if err := sock.SetDeadline(time.Now().Add(10 * time.Second)); err != nil { fmt.Println("Couldn't set the socket timeout:", err) os.Exit(1) } n, err := sock.WriteTo(request, serverAddr) if err != nil { fmt.Println("Couldn't send STUN request:", err) os.Exit(1) } if n < len(request) { fmt.Println("Short write") os.Exit(1) } buf := make([]byte, 1024) n, _, err = sock.ReadFromUDP(buf) if err != nil { fmt.Println("Error reading STUN response:", err) os.Exit(1) } sock.Close() packet, err := stun.ParsePacket(buf[:n], nil) if err != nil { fmt.Println("Failed to parse STUN packet:", err) os.Exit(1) } if packet.Error != nil { fmt.Println("STUN server returned an error:", packet.Error) os.Exit(1) } if packet.Addr == nil { fmt.Println("STUN server didn't provide a reflexive address") os.Exit(1) } fmt.Printf("According to STUN server %s, port %d maps to %s on your NAT\n", *server, *sourcePort, packet.Addr) }