Browse Source

Cleanup.

pull/2/head
Justine Alexandra Roberts Tunney 11 years ago
parent
commit
6d5fefb27b
5 changed files with 75 additions and 67 deletions
  1. +55
    -60
      sip/dialog.go
  2. +0
    -1
      sip/messages.go
  3. +12
    -5
      sip/receiver.go
  4. +1
    -1
      sip/transport.go
  5. +7
    -0
      sip/util.go

+ 55
- 60
sip/dialog.go View File

@ -14,7 +14,6 @@ import (
) )
const ( const (
DialogInit = 0
DialogProceeding = 1 DialogProceeding = 1
DialogRinging = 2 DialogRinging = 2
DialogAnswered = 3 DialogAnswered = 3
@ -24,7 +23,7 @@ const (
) )
var ( var (
looseSignalling = flag.Bool("looseSignalling", false, "Permit SIP messages from servers other than the next hop.")
looseSignalling = flag.Bool("looseSignalling", true, "Permit SIP messages from servers other than the next hop.")
) )
// Dialog represents an outbound SIP phone call. // Dialog represents an outbound SIP phone call.
@ -87,7 +86,7 @@ func NewDialog(invite *Msg) (dl *Dialog, err error) {
func (dls *dialogState) run() { func (dls *dialogState) run() {
defer dls.sabotage() defer dls.sabotage()
defer dls.cleanup() defer dls.cleanup()
if !dls.sendRequest(dls.invite, true) {
if !dls.sendRequest(dls.invite) {
return return
} }
for { for {
@ -129,12 +128,13 @@ func (dls *dialogState) run() {
} }
} }
func (dls *dialogState) sendRequest(request *Msg, wantSRV bool) bool {
func (dls *dialogState) sendRequest(request *Msg) bool {
host, port, err := RouteMessage(nil, nil, request) host, port, err := RouteMessage(nil, nil, request)
if err != nil { if err != nil {
dls.errChan <- err dls.errChan <- err
return false return false
} }
wantSRV := dls.state < DialogAnswered
routes, err := RouteAddress(host, port, wantSRV) routes, err := RouteAddress(host, port, wantSRV)
if err != nil { if err != nil {
dls.errChan <- err dls.errChan <- err
@ -156,73 +156,69 @@ func (dls *dialogState) popRoute() bool {
if !dls.connect() { if !dls.connect() {
return dls.popRoute() return dls.popRoute()
} }
PopulateMessage(nil, nil, dls.request)
dls.lseq = dls.request.CSeq
dls.populate(dls.request)
if dls.state < DialogAnswered {
dls.rseq = 0
dls.remote = nil
dls.lseq = dls.request.CSeq
}
dls.requestResends = 0 dls.requestResends = 0
dls.requestTimer = time.After(resendInterval) dls.requestTimer = time.After(resendInterval)
return dls.send(dls.request) return dls.send(dls.request)
} }
func (dls *dialogState) connect() bool { func (dls *dialogState) connect() bool {
if dls.sock != nil && dls.sock.RemoteAddr().String() == dls.addr {
return true
}
if dls.sock == nil || dls.sock.RemoteAddr().String() != dls.addr {
// Create socket through which we send messages. This socket is connected to
// the remote address so we can receive ICMP unavailable errors. It also
// allows us to discover the appropriate IP address for this machine.
dls.cleanupSock()
conn, err := net.Dial("udp", dls.addr)
if err != nil {
log.Printf("net.Dial(udp, %s) failed: %s", dls.addr, err)
return false
}
dls.sock = conn.(*net.UDPConn)
sockMsgs := make(chan *Msg)
sockErrs := make(chan error)
dls.sockMsgs = sockMsgs
dls.sockErrs = sockErrs
go ReceiveMessages(dls.sock, sockMsgs, sockErrs)
// Create socket through which we send messages. This socket is connected to
// the remote address so we can receive ICMP unavailable errors. It also
// allows us to discover the appropriate IP address for this machine.
dls.cleanupSock()
conn, err := net.Dial("udp", dls.addr)
if err != nil {
log.Printf("net.Dial(udp, %s) failed: %s", dls.addr, err)
return false
// But a connected UDP socket can only receive packets from a single host.
// SIP signalling paths can change depending on the environment, so we need
// to be able to accept packets from anyone.
if dls.csock == nil && *looseSignalling {
cconn, err := net.ListenPacket("udp", ":0")
if err != nil {
log.Printf("net.ListenPacket(udp, :0) failed: %s", err)
return false
}
dls.csock = cconn.(*net.UDPConn)
csockMsgs := make(chan *Msg)
csockErrs := make(chan error)
dls.csockMsgs = csockMsgs
dls.csockErrs = csockErrs
go ReceiveMessages(dls.csock, csockMsgs, csockErrs)
}
} }
dls.sock = conn.(*net.UDPConn)
dls.rseq = 0
dls.remote = nil
laddr := conn.LocalAddr().(*net.UDPAddr)
return true
}
func (dls *dialogState) populate(msg *Msg) {
laddr := dls.sock.LocalAddr().(*net.UDPAddr)
lhost := laddr.IP.String() lhost := laddr.IP.String()
lport := uint16(laddr.Port) lport := uint16(laddr.Port)
dls.request.Via = &Via{
msg.Via = &Via{
Host: lhost, Host: lhost,
Port: lport, Port: lport,
Params: Params{"branch": util.GenerateBranch()}, Params: Params{"branch": util.GenerateBranch()},
} }
sockMsgs := make(chan *Msg)
sockErrs := make(chan error)
dls.sockMsgs = sockMsgs
dls.sockErrs = sockErrs
go ReceiveMessages(dls.request.Contact, dls.sock, sockMsgs, sockErrs)
// But a connected UDP socket can only receive packets from a single host.
// SIP signalling paths can change depending on the environment, so we need
// to be able to accept packets from anyone.
if *looseSignalling {
if dls.csock == nil {
cconn, err := net.ListenPacket("udp", ":0")
if err != nil {
log.Printf("net.ListenPacket(udp, :0) failed: %s", err)
return false
}
dls.csock = cconn.(*net.UDPConn)
dls.request.Contact = &Addr{
Uri: &URI{
Scheme: "sip",
Host: lhost,
Port: uint16(dls.csock.LocalAddr().(*net.UDPAddr).Port),
Params: Params{"transport": "udp"},
},
}
} else {
dls.request.Contact.Uri.Host = lhost
if msg.Contact == nil {
if dls.csock != nil {
lport = uint16(dls.csock.LocalAddr().(*net.UDPAddr).Port)
} }
csockMsgs := make(chan *Msg)
csockErrs := make(chan error)
dls.csockMsgs = csockMsgs
dls.csockErrs = csockErrs
go ReceiveMessages(dls.request.Contact, dls.csock, csockMsgs, csockErrs)
} else {
dls.request.Contact = &Addr{
msg.Contact = &Addr{
Uri: &URI{ Uri: &URI{
Scheme: "sip", Scheme: "sip",
Host: lhost, Host: lhost,
@ -231,8 +227,7 @@ func (dls *dialogState) connect() bool {
}, },
} }
} }
return true
PopulateMessage(nil, nil, msg)
} }
func (dls *dialogState) handleMessage(msg *Msg) bool { func (dls *dialogState) handleMessage(msg *Msg) bool {
@ -300,7 +295,7 @@ func (dls *dialogState) handleResponse(msg *Msg) bool {
case StatusMovedPermanently, StatusMovedTemporarily: case StatusMovedPermanently, StatusMovedTemporarily:
dls.invite.Request = msg.Contact.Uri dls.invite.Request = msg.Contact.Uri
dls.invite.Route = nil dls.invite.Route = nil
return dls.sendRequest(dls.invite, true)
return dls.sendRequest(dls.invite)
default: default:
if msg.Status > StatusOK { if msg.Status > StatusOK {
dls.errChan <- &ResponseError{Msg: msg} dls.errChan <- &ResponseError{Msg: msg}
@ -435,7 +430,7 @@ func (dls *dialogState) sendHangup() bool {
case DialogProceeding, DialogRinging: case DialogProceeding, DialogRinging:
return dls.send(NewCancel(dls.invite)) return dls.send(NewCancel(dls.invite))
case DialogAnswered: case DialogAnswered:
return dls.sendRequest(NewBye(dls.invite, dls.remote, &dls.lseq), false)
return dls.sendRequest(NewBye(dls.invite, dls.remote, &dls.lseq))
case DialogHangup: case DialogHangup:
panic("Why didn't the event loop break?") panic("Why didn't the event loop break?")
default: default:


+ 0
- 1
sip/messages.go View File

@ -85,7 +85,6 @@ func NewBye(invite, remote *Msg, lseq *int) *Msg {
return &Msg{ return &Msg{
Method: MethodBye, Method: MethodBye,
Request: remote.Contact.Uri, Request: remote.Contact.Uri,
Via: invite.Via.Copy().Branch(),
From: invite.From, From: invite.From,
To: remote.To, To: remote.To,
CallID: invite.CallID, CallID: invite.CallID,


+ 12
- 5
sip/receiver.go View File

@ -7,8 +7,11 @@ import (
"time" "time"
) )
func ReceiveMessages(contact *Addr, sock *net.UDPConn, c chan<- *Msg, e chan<- error) {
func ReceiveMessages(sock *net.UDPConn, c chan<- *Msg, e chan<- error) {
buf := make([]byte, 2048) buf := make([]byte, 2048)
laddr := sock.LocalAddr().(*net.UDPAddr)
lhost := laddr.IP.String()
lport := uint16(laddr.Port)
for { for {
amt, addr, err := sock.ReadFromUDP(buf) amt, addr, err := sock.ReadFromUDP(buf)
if err != nil { if err != nil {
@ -27,10 +30,10 @@ func ReceiveMessages(contact *Addr, sock *net.UDPConn, c chan<- *Msg, e chan<- e
} }
addReceived(msg, addr) addReceived(msg, addr)
addTimestamp(msg, ts) addTimestamp(msg, ts)
if contact.CompareHostPort(msg.Route) {
if msg.Route != nil && msg.Route.Uri.Host == lhost && or5060(msg.Route.Uri.Port) == lport {
msg.Route = msg.Route.Next msg.Route = msg.Route.Next
} }
fixMessagesFromStrictRouters(contact, msg)
fixMessagesFromStrictRouters(lhost, lport, msg)
c <- msg c <- msg
} }
close(c) close(c)
@ -51,8 +54,12 @@ func addTimestamp(msg *Msg, ts time.Time) {
// RFC3261 16.4 Route Information Preprocessing // RFC3261 16.4 Route Information Preprocessing
// RFC3261 16.12.1.2: Traversing a Strict-Routing Proxy // RFC3261 16.12.1.2: Traversing a Strict-Routing Proxy
func fixMessagesFromStrictRouters(contacts *Addr, msg *Msg) {
if msg.Request != nil && msg.Request.Params.Has("lr") && msg.Route != nil && contacts.Uri.CompareHostPort(msg.Request) {
func fixMessagesFromStrictRouters(lhost string, lport uint16, msg *Msg) {
if msg.Request != nil &&
msg.Request.Params.Has("lr") &&
msg.Route != nil &&
msg.Request.Host == lhost &&
or5060(msg.Request.Port) == lport {
var oldReq, newReq *URI var oldReq, newReq *URI
if msg.Route.Next == nil { if msg.Route.Next == nil {
oldReq, newReq = msg.Request, msg.Route.Uri oldReq, newReq = msg.Request, msg.Route.Uri


+ 1
- 1
sip/transport.go View File

@ -50,7 +50,7 @@ func NewTransport(contact *Addr) (tp *Transport, err error) {
Port: uint16(addr.Port), Port: uint16(addr.Port),
}, },
} }
go ReceiveMessages(contact, sock, c, e)
go ReceiveMessages(sock, c, e)
return return
} }


+ 7
- 0
sip/util.go View File

@ -6,6 +6,13 @@ import (
"strings" "strings"
) )
func or5060(port uint16) uint16 {
if port == 0 {
return 5060
}
return port
}
func portstr(port uint16) string { func portstr(port uint16) string {
return strconv.FormatInt(int64(port), 10) return strconv.FormatInt(int64(port), 10)
} }


Loading…
Cancel
Save