// Copyright 2020 Justine Alexandra Roberts Tunney // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package sip import ( "log" "net" "strconv" "time" ) func ReceiveMessages(sock *net.UDPConn, c chan<- *Msg, e chan<- error) { buf := make([]byte, 2048) laddr := sock.LocalAddr().(*net.UDPAddr) lhost := laddr.IP.String() lport := uint16(laddr.Port) for { amt, addr, err := sock.ReadFromUDP(buf) if err != nil { e <- err break } ts := time.Now() packet := buf[0:amt] if *tracing { trace("recv", packet, addr) } msg, err := ParseMsg(packet) if err != nil { log.Printf("Dropping SIP message: %s\r\n", err) continue } addReceived(msg, addr) addTimestamp(msg, ts) if msg.Route != nil && msg.Route.Uri.Host == lhost && or5060(msg.Route.Uri.Port) == lport { msg.Route = msg.Route.Next } fixMessagesFromStrictRouters(lhost, lport, msg) c <- msg } close(c) close(e) // Must be unbuffered! } func addReceived(msg *Msg, addr *net.UDPAddr) { if msg.IsResponse() { return } if int(msg.Via.Port) != addr.Port { rport := msg.Via.Param.Get("rport") port := strconv.Itoa(addr.Port) if rport == nil { msg.Via.Param = &Param{"rport", port, msg.Via.Param} } else { // implied rport is 5060, but some NAT will use another port,we use real port instead if len(rport.Value) == 0 { rport.Value = port } } } if msg.Via.Host != addr.IP.String() { if msg.Via.Param.Get("received") == nil { msg.Via.Param = &Param{"received", addr.IP.String(), msg.Via.Param} } } } func addTimestamp(msg *Msg, ts time.Time) { if *timestampTagging { msg.Via.Param = &Param{"usi", strconv.FormatInt(ts.UnixNano()/int64(time.Microsecond), 10), msg.Via.Param} } } // RFC3261 16.4 Route Information Preprocessing // RFC3261 16.12.1.2: Traversing a Strict-Routing Proxy func fixMessagesFromStrictRouters(lhost string, lport uint16, msg *Msg) { if msg.Request != nil && msg.Request.Param.Get("lr") != nil && msg.Route != nil && msg.Request.Host == lhost && or5060(msg.Request.Port) == lport { var oldReq, newReq *URI if msg.Route.Next == nil { oldReq, newReq = msg.Request, msg.Route.Uri msg.Request = msg.Route.Uri msg.Route = nil } else { seclast := msg.Route for ; seclast.Next.Next != nil; seclast = seclast.Next { } oldReq, newReq = msg.Request, seclast.Next.Uri msg.Request = seclast.Next.Uri seclast.Next = nil msg.Route.Last() } log.Printf("Fixing request URI after strict router traversal: %s -> %s\r\n", oldReq, newReq) } }