|
|
|
@ -2,12 +2,16 @@ package sip |
|
|
|
|
|
|
|
import ( |
|
|
|
"errors" |
|
|
|
"log" |
|
|
|
"net" |
|
|
|
) |
|
|
|
|
|
|
|
func RouteMessage(via *Via, contact *Addr, old *Msg) (msg *Msg, dest string, err error) { |
|
|
|
var host string |
|
|
|
var port uint16 |
|
|
|
type AddressRoute struct { |
|
|
|
Address string |
|
|
|
Next *AddressRoute |
|
|
|
} |
|
|
|
|
|
|
|
func RouteMessage(via *Via, contact *Addr, old *Msg) (msg *Msg, host string, port uint16, err error) { |
|
|
|
msg = new(Msg) |
|
|
|
*msg = *old // Start off with a shallow copy.
|
|
|
|
if msg.Contact == nil { |
|
|
|
@ -17,10 +21,9 @@ func RouteMessage(via *Via, contact *Addr, old *Msg) (msg *Msg, dest string, err |
|
|
|
if via.CompareHostPort(msg.Via) { |
|
|
|
msg.Via = msg.Via.Next |
|
|
|
} |
|
|
|
host, port = msg.Via.Host, msg.Via.Port |
|
|
|
if received, ok := msg.Via.Params["received"]; ok { |
|
|
|
return msg, received, nil |
|
|
|
} else { |
|
|
|
host, port = msg.Via.Host, msg.Via.Port |
|
|
|
host = received |
|
|
|
} |
|
|
|
} else { |
|
|
|
if contact.CompareHostPort(msg.Route) { |
|
|
|
@ -28,23 +31,50 @@ func RouteMessage(via *Via, contact *Addr, old *Msg) (msg *Msg, dest string, err |
|
|
|
} |
|
|
|
if msg.Route != nil { |
|
|
|
if msg.Method == "REGISTER" { |
|
|
|
return nil, "", errors.New("Don't route REGISTER requests") |
|
|
|
return nil, "", 0, errors.New("Don't route REGISTER requests") |
|
|
|
} |
|
|
|
if msg.Route.Uri.Params.Has("lr") { |
|
|
|
// RFC3261 16.12.1.1 Basic SIP Trapezoid
|
|
|
|
host, port = msg.Route.Uri.Host, msg.Route.Uri.GetPort() |
|
|
|
host, port = msg.Route.Uri.Host, msg.Route.Uri.Port |
|
|
|
} else { |
|
|
|
// RFC3261 16.12.1.2: Traversing a Strict-Routing Proxy
|
|
|
|
msg.Route = old.Route.Copy() |
|
|
|
msg.Route.Last().Next = &Addr{Uri: msg.Request} |
|
|
|
msg.Request = msg.Route.Uri |
|
|
|
msg.Route = msg.Route.Next |
|
|
|
host, port = msg.Request.Host, msg.Request.GetPort() |
|
|
|
host, port = msg.Request.Host, msg.Request.Port |
|
|
|
} |
|
|
|
} else { |
|
|
|
host, port = msg.Request.Host, msg.Request.GetPort() |
|
|
|
host, port = msg.Request.Host, msg.Request.Port |
|
|
|
} |
|
|
|
} |
|
|
|
dest = net.JoinHostPort(host, portstr(port)) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func RouteAddress(host string, port uint16) (routes *AddressRoute, err error) { |
|
|
|
if net.ParseIP(host) != nil { |
|
|
|
if port == 0 { |
|
|
|
port = 5060 |
|
|
|
} |
|
|
|
return &AddressRoute{Address: net.JoinHostPort(host, portstr(port))}, nil |
|
|
|
} |
|
|
|
if port == 0 { |
|
|
|
_, srvs, err := net.LookupSRV("sip", "udp", host) |
|
|
|
if err == nil && len(srvs) > 0 { |
|
|
|
for i := len(srvs) - 1; i >= 0; i-- { |
|
|
|
routes = &AddressRoute{ |
|
|
|
Address: net.JoinHostPort(srvs[i].Target, portstr(srvs[i].Port)), |
|
|
|
Next: routes, |
|
|
|
} |
|
|
|
} |
|
|
|
return routes, nil |
|
|
|
} |
|
|
|
log.Println("net.LookupSRV(sip, udp, %s) failed: %s", err) |
|
|
|
port = 5060 |
|
|
|
} |
|
|
|
addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(host, portstr(port))) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
return &AddressRoute{Address: addr.String()}, nil |
|
|
|
} |