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 (
DialogInit = 0
DialogProceeding = 1
DialogRinging = 2
DialogAnswered = 3
@ -24,7 +23,7 @@ const (
)
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.
@ -87,7 +86,7 @@ func NewDialog(invite *Msg) (dl *Dialog, err error) {
func (dls *dialogState) run() {
defer dls.sabotage()
defer dls.cleanup()
if !dls.sendRequest(dls.invite, true) {
if !dls.sendRequest(dls.invite) {
return
}
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)
if err != nil {
dls.errChan <- err
return false
}
wantSRV := dls.state < DialogAnswered
routes, err := RouteAddress(host, port, wantSRV)
if err != nil {
dls.errChan <- err
@ -156,73 +156,69 @@ func (dls *dialogState) popRoute() bool {
if !dls.connect() {
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.requestTimer = time.After(resendInterval)
return dls.send(dls.request)
}
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()
lport := uint16(laddr.Port)
dls.request.Via = &Via{
msg.Via = &Via{
Host: lhost,
Port: lport,
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{
Scheme: "sip",
Host: lhost,
@ -231,8 +227,7 @@ func (dls *dialogState) connect() bool {
},
}
}
return true
PopulateMessage(nil, nil, msg)
}
func (dls *dialogState) handleMessage(msg *Msg) bool {
@ -300,7 +295,7 @@ func (dls *dialogState) handleResponse(msg *Msg) bool {
case StatusMovedPermanently, StatusMovedTemporarily:
dls.invite.Request = msg.Contact.Uri
dls.invite.Route = nil
return dls.sendRequest(dls.invite, true)
return dls.sendRequest(dls.invite)
default:
if msg.Status > StatusOK {
dls.errChan <- &ResponseError{Msg: msg}
@ -435,7 +430,7 @@ func (dls *dialogState) sendHangup() bool {
case DialogProceeding, DialogRinging:
return dls.send(NewCancel(dls.invite))
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:
panic("Why didn't the event loop break?")
default:


+ 0
- 1
sip/messages.go View File

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


+ 12
- 5
sip/receiver.go View File

@ -7,8 +7,11 @@ import (
"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)
laddr := sock.LocalAddr().(*net.UDPAddr)
lhost := laddr.IP.String()
lport := uint16(laddr.Port)
for {
amt, addr, err := sock.ReadFromUDP(buf)
if err != nil {
@ -27,10 +30,10 @@ func ReceiveMessages(contact *Addr, sock *net.UDPConn, c chan<- *Msg, e chan<- e
}
addReceived(msg, addr)
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
}
fixMessagesFromStrictRouters(contact, msg)
fixMessagesFromStrictRouters(lhost, lport, msg)
c <- msg
}
close(c)
@ -51,8 +54,12 @@ func addTimestamp(msg *Msg, ts time.Time) {
// RFC3261 16.4 Route Information Preprocessing
// 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
if msg.Route.Next == nil {
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),
},
}
go ReceiveMessages(contact, sock, c, e)
go ReceiveMessages(sock, c, e)
return
}


+ 7
- 0
sip/util.go View File

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


Loading…
Cancel
Save