func (this *Server) handleConnection(out net.Conn, ip net.IP, port int) { req, err := msg.DecodeMessage(out) if err != nil { log.Println(err) return } conn := &Connection{Req: req, Out: out, Realm: Realm} switch req.Type() { case msg.Binding | msg.Request: if this.auth == nil { log.Println("Binding to address:", ip, port) res := msg.NewResponse(msg.Success, req) xorAddr := msg.NewXORAddress(ip, port, res.Header()) res.AddAttribute(xorAddr) out.Write(res.EncodeMessage()) this.conns <- conn return } if this.Validate(conn) { conn.Write(msg.NewResponse(msg.Success, req)) this.conns <- conn } default: // Unrecognized messages this.conns <- conn } }
// Sends a request where you expect to get a response back func (this *Client) SendReqRes(req *msg.Message) (*Connection, error) { conn, err := net.DialTimeout("tcp", this.server, 15*time.Second) if err != nil { log.Println("Failed to create connection: ", err) return nil, err } laddr := conn.LocalAddr() ip := laddr.(*net.TCPAddr).IP port := laddr.(*net.TCPAddr).Port xor := msg.NewXORAddress(ip, port, req.Header()) req.AddAttribute(xor) if this.nonce != nil && this.realm != nil { req.AddAttribute(this.user) req.AddAttribute(this.realm) req.AddAttribute(this.nonce) username := this.user.String() realm := this.realm.String() integrity := msg.NewIntegrityAttr(username, this.password, realm, req) req.AddAttribute(integrity) } conn.Write(req.EncodeMessage()) res, err := msg.DecodeMessage(conn) if err != nil { conn.Close() return nil, err } if eattr, err := res.Attribute(msg.ErrorCode); err == nil { if code, err := eattr.(*msg.StunError).Code(); err == nil { log.Println("error code", code) switch code { case msg.StaleNonce: log.Println("Stale Nonce, calling authenticate...") return this.Authenticate(res, req) case msg.Unauthorized: log.Println("unauthorized") if _, err := req.Attribute(msg.MessageIntegrity); err == nil { conn.Close() return nil, errors.New("Invalid credentials") } else { return this.Authenticate(res, req) } } } } return &Connection{res, conn}, nil }
func (this *Connection) Write(res *msg.Message) { xorAddr := msg.NewXORAddress(this.IP(), this.Port(), res.Header()) res.AddAttribute(xorAddr) if this.HasAuth { i := msg.NewIntegrityAttr(this.User, this.Passwd, this.Realm, this.Req) res.AddAttribute(i) } this.Out.Write(res.EncodeMessage()) }