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 }