Browse Source

Mess with things.

pull/2/head
Justine Alexandra Roberts Tunney 11 years ago
parent
commit
8a8009559a
14 changed files with 96 additions and 163 deletions
  1. +1
    -0
      README.md
  2. +1
    -0
      dsp/dsp_amd64.s
  3. +5
    -4
      example/echo2/echo2_test.go
  4. +3
    -3
      rtp/session.go
  5. +4
    -5
      sip/addr.go
  6. +10
    -46
      sip/addr_test.go
  7. +5
    -5
      sip/messages.go
  8. +0
    -2
      sip/msg_test.go
  9. +15
    -15
      sip/transport.go
  10. +18
    -20
      sip/uri.go
  11. +29
    -45
      sip/uri_test.go
  12. +4
    -1
      sip/util.go
  13. +1
    -6
      sip/via.go
  14. +0
    -11
      util/util.go

+ 1
- 0
README.md View File

@ -67,3 +67,4 @@ This is what a sip stack looks like:
- [RTP (RFC 3550)](https://tools.ietf.org/html/rfc3550)
- [RTP DTMF (RFC 4733)](https://tools.ietf.org/html/rfc4733)
- [SIP 100rel (RFC 3262)](https://tools.ietf.org/html/rfc3262)
- [SIP: Locating a Server (RFC 3263)](https://tools.ietf.org/html/rfc3263)

+ 1
- 0
dsp/dsp_amd64.s View File

@ -1,6 +1,7 @@
#define ULAW_BIAS $0x84
// func L16MixSat160(dst, src *int16)
// Explanation: http://i.imgur.com/nejgQ41.jpg
TEXT ·L16MixSat160(SB),4,$0-16
MOVQ dst+0(FP), AX
MOVQ src+8(FP), BX


+ 5
- 4
example/echo2/echo2_test.go View File

@ -42,7 +42,7 @@ func TestCallToEchoApp(t *testing.T) {
// We're going to send white noise every 20ms.
var frame rtp.Frame
awgn := dsp.NewAWGN(-25.0)
awgn := dsp.NewAWGN(-45.0)
ticker := time.NewTicker(20 * time.Millisecond)
defer ticker.Stop()
@ -130,14 +130,13 @@ loop:
if resends == 2 {
t.Fatal("Failed to send", resend.Method)
}
resends++
err = tp.Send(resend)
if err != nil {
t.Fatal("SIP send failed:", err)
}
case <-deathTimer:
resends = 0
resends++
resendTimer = time.After(resendInterval)
case <-deathTimer:
if answered {
resend = sip.NewBye(invite, msg)
} else {
@ -147,6 +146,8 @@ loop:
if err != nil {
t.Error("SIP send failed:", err)
}
resends = 0
resendTimer = time.After(resendInterval)
}
}


+ 3
- 3
rtp/session.go View File

@ -7,9 +7,9 @@ import (
"fmt"
"github.com/jart/gosip/dsp"
"github.com/jart/gosip/sdp"
"github.com/jart/gosip/util"
"math/rand"
"net"
"strconv"
"strings"
)
@ -125,8 +125,8 @@ func (rs *Session) recv() (frame *Frame, err error) {
func listenRTP(host string) (sock net.PacketConn, err error) {
for i := 0; i < rtpBindMaxAttempts; i++ {
port := rtpBindPortMin + rand.Int()%(rtpBindPortMax-rtpBindPortMin+1)
saddr := util.HostPortToString(host, uint16(port))
port := rtpBindPortMin + rand.Int63()%(rtpBindPortMax-rtpBindPortMin+1)
saddr := net.JoinHostPort(host, strconv.FormatInt(port, 10))
sock, err = net.ListenPacket("udp", saddr)
if err != nil {
if !strings.Contains(err.Error(), "address already in use") {


+ 4
- 5
sip/addr.go View File

@ -137,7 +137,6 @@ func (addr *Addr) Or(other *Addr) *Addr {
// Sets newly generated tag ID and returns self.
func (addr *Addr) Tag() *Addr {
addr = addr.Copy()
addr.Params["tag"] = util.GenerateTag()
return addr
}
@ -172,11 +171,11 @@ func (addr *Addr) Copy() *Addr {
return res
}
// Returns true if the host and port match. If a username is present in
// `addr`, then the username is `other` must also match.
func (addr *Addr) Compare(other *Addr) bool {
func (addr *Addr) CompareHostPort(other *Addr) bool {
if addr != nil && other != nil {
return addr.Uri.Compare(other.Uri)
if addr.Uri.CompareHostPort(other.Uri) {
return true
}
}
return false
}


+ 10
- 46
sip/addr_test.go View File

@ -8,7 +8,6 @@ import (
type addrTest struct {
s string
s2 string
addr sip.Addr
err error
}
@ -16,13 +15,11 @@ type addrTest struct {
var addrTests = []addrTest{
addrTest{
s: "<sip:pokémon.net>",
s2: "<sip:pok%c3%a9mon.net>",
s: "<sip:pokemon.net>",
addr: sip.Addr{
Uri: &sip.URI{
Scheme: "sip",
Host: "pokémon.net",
Port: 5060,
Host: "pokemon.net",
},
},
},
@ -34,7 +31,6 @@ var addrTests = []addrTest{
Scheme: "sip",
User: "brave",
Host: "toaster.net",
Port: 5060,
Params: sip.Params{
"isup-oli": "29",
},
@ -46,12 +42,11 @@ var addrTests = []addrTest{
},
addrTest{
s: `<sip:pokemon.com>, "Ditto" <sip:ditto@pokemon.com>`,
s: `<sip:pokemon.com>,"Ditto" <sip:ditto@pokemon.com>`,
addr: sip.Addr{
Uri: &sip.URI{
Scheme: "sip",
Host: "pokemon.com",
Port: 5060,
},
Next: &sip.Addr{
Display: "Ditto",
@ -59,67 +54,42 @@ var addrTests = []addrTest{
Scheme: "sip",
User: "ditto",
Host: "pokemon.com",
Port: 5060,
},
},
},
},
addrTest{
s: `<sip:1.2.3.4>, <sip:1.2.3.5>, <sip:[666::dead:beef]>`,
s: `<sip:1.2.3.4>,<sip:1.2.3.5>,<sip:[666::dead:beef]>`,
addr: sip.Addr{
Uri: &sip.URI{
Scheme: "sip",
Host: "1.2.3.4",
Port: 5060,
},
Next: &sip.Addr{
Uri: &sip.URI{
Scheme: "sip",
Host: "1.2.3.5",
Port: 5060,
},
Next: &sip.Addr{
Uri: &sip.URI{
Scheme: "sip",
Host: "666::dead:beef",
Port: 5060,
},
},
},
},
},
addrTest{
s: " hello kitty <sip:jtunney@bsdtelecom.net;isup-oli=29>;tag=deadbeef",
s2: "\"hello kitty\" <sip:jtunney@bsdtelecom.net;isup-oli=29>;tag=deadbeef",
addr: sip.Addr{
Display: "hello kitty",
Uri: &sip.URI{
Scheme: "sip",
User: "jtunney",
Host: "bsdtelecom.net",
Port: 5060,
Params: sip.Params{
"isup-oli": "29",
},
},
Params: sip.Params{
"tag": "deadbeef",
},
},
},
addrTest{
s: "\"\\\"\\\"Justine \\\\Tunney \" " +
"<sip:jtunney@bsdtelecom.net;isup-oli=29>;tag=deadbeef",
"<sip:jart@google.com;isup-oli=29>;tag=deadbeef",
addr: sip.Addr{
Display: "\"\"Justine \\Tunney ",
Uri: &sip.URI{
Scheme: "sip",
User: "jtunney",
Host: "bsdtelecom.net",
Port: 5060,
User: "jart",
Host: "google.com",
Params: sip.Params{
"isup-oli": "29",
},
@ -143,7 +113,7 @@ func TestParseAddr(t *testing.T) {
}
}
if !reflect.DeepEqual(&test.addr, addr) {
t.Errorf("%#v != %#v", &test.addr, addr)
t.Errorf("%#v != %#v\n%#v != %#v", &test.addr, addr, test.addr.Uri, addr.Uri)
}
}
}
@ -151,14 +121,8 @@ func TestParseAddr(t *testing.T) {
func TestAddrString(t *testing.T) {
for _, test := range addrTests {
addr := test.addr.String()
var s string
if test.s2 != "" {
s = test.s2
} else {
s = test.s
}
if s != addr {
t.Error(s, "!=", addr)
if test.s != addr {
t.Error(test.s, "!=", addr)
}
}
}


+ 5
- 5
sip/messages.go View File

@ -14,10 +14,10 @@ const (
func NewRequest(tp *Transport, method string, to, from *Addr) *Msg {
return &Msg{
Method: method,
Request: to.Uri,
Request: to.Uri.Copy(),
Via: tp.Via.Copy().Branch(),
From: from.Or(tp.Contact).Tag(),
To: to,
From: from.Or(tp.Contact).Copy().Tag(),
To: to.Copy(),
CallID: util.GenerateCallID(),
CSeq: util.GenerateCSeq(),
CSeqMethod: method,
@ -96,7 +96,7 @@ func ResponseMatch(msg, resp *Msg) bool {
return (resp.IsResponse &&
resp.CSeq == msg.CSeq &&
resp.CSeqMethod == msg.Method &&
resp.Via.Last().Compare(msg.Via))
resp.Via.Last().CompareHostPort(msg.Via))
}
// Returns true if `ack` can be considered an appropriate response to `msg`.
@ -107,7 +107,7 @@ func AckMatch(msg, ack *Msg) bool {
ack.Method == MethodAck &&
ack.CSeq == msg.CSeq &&
ack.CSeqMethod == MethodAck &&
ack.Via.Last().CompareAddr(msg.Via))
ack.Via.Last().CompareHostPort(msg.Via))
}
func AttachSDP(msg *Msg, ms *sdp.SDP) {


+ 0
- 2
sip/msg_test.go View File

@ -115,7 +115,6 @@ var msgTests = []msgTest{
Request: &sip.URI{
Scheme: "sip",
Host: "10.11.34.37",
Port: 5060,
},
Via: &sip.Via{
Version: "2.0",
@ -128,7 +127,6 @@ var msgTests = []msgTest{
Uri: &sip.URI{
Scheme: "sip",
Host: "10.11.34.37",
Port: 5060,
},
},
From: &sip.Addr{


+ 15
- 15
sip/transport.go View File

@ -7,7 +7,6 @@ import (
"bytes"
"errors"
"flag"
"github.com/jart/gosip/util"
"log"
"net"
"strconv"
@ -52,7 +51,7 @@ type Transport struct {
// user-agents where to send responses and hence should only contain an IP or
// canonical address.
func NewTransport(contact *Addr) (tp *Transport, err error) {
saddr := util.HostPortToString(contact.Uri.Host, contact.Uri.Port)
saddr := net.JoinHostPort(contact.Uri.Host, portstr(contact.Uri.Port))
sock, err := net.ListenPacket("udp", saddr)
if err != nil {
return nil, err
@ -173,12 +172,12 @@ func (tp *Transport) sanityCheck(msg *Msg) error {
// Perform some ingress message mangling.
func (tp *Transport) preprocess(msg *Msg) {
if tp.Contact.Compare(msg.Route) {
if tp.Contact.CompareHostPort(msg.Route) {
log.Printf("Removing our route header: %s", msg.Route)
msg.Route = msg.Route.Next
}
if msg.Request != nil && msg.Request.Params.Has("lr") && msg.Route != nil && tp.Contact.Uri.Compare(msg.Request) {
if msg.Request != nil && msg.Request.Params.Has("lr") && msg.Route != nil && tp.Contact.Uri.CompareHostPort(msg.Request) {
// RFC3261 16.4 Route Information Preprocessing
// RFC3261 16.12.1.2: Traversing a Strict-Routing Proxy
var oldReq, newReq *URI
@ -208,8 +207,8 @@ func (tp *Transport) route(old *Msg) (msg *Msg, dest string, err error) {
msg.Contact = tp.Contact
}
if msg.IsResponse {
if msg.Via.CompareAddr(tp.Via) {
// In proxy scenarios we have to remove our own Via.
if msg.Via.CompareHostPort(tp.Via) {
// In proxy scenarios, we have to remove our own Via.
msg.Via = msg.Via.Next
}
if msg.Via == nil {
@ -224,8 +223,12 @@ func (tp *Transport) route(old *Msg) (msg *Msg, dest string, err error) {
if msg.Request == nil {
return nil, "", errors.New("Missing request URI")
}
if !msg.Via.CompareAddr(tp.Via) {
return nil, "", errors.New("You forgot to say: msg.Via = tp.Via(msg.Via)")
if !msg.Via.CompareHostPort(tp.Via) {
return nil, "", errors.New("Set our Via should come first when sending messages")
}
if msg.Route.CompareHostPort(tp.Contact) {
// In proxy scenarios, we have to remove our own Route.
msg.Route = msg.Route.Next
}
if msg.Route != nil {
if msg.Method == "REGISTER" {
@ -233,23 +236,20 @@ func (tp *Transport) route(old *Msg) (msg *Msg, dest string, err error) {
}
if msg.Route.Uri.Params.Has("lr") {
// RFC3261 16.12.1.1 Basic SIP Trapezoid
route := msg.Route
// TODO(jart): Remove if same as Contact.
// msg.Route = msg.Route.Next
host, port = route.Uri.Host, route.Uri.Port
host, port = msg.Route.Uri.Host, msg.Route.Uri.GetPort()
} 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.Port
host, port = msg.Request.Host, msg.Request.GetPort()
}
} else {
host, port = msg.Request.Host, msg.Request.Port
host, port = msg.Request.Host, msg.Request.GetPort()
}
}
dest = util.HostPortToString(host, port)
dest = net.JoinHostPort(host, portstr(port))
return
}


+ 18
- 20
sip/uri.go View File

@ -24,7 +24,6 @@ import (
"bytes"
"errors"
"github.com/jart/gosip/util"
"strconv"
"strings"
)
@ -156,30 +155,32 @@ func (uri *URI) Append(b *bytes.Buffer) {
b.WriteString(util.URLEscape(uri.Host, false))
}
if uri.Port > 0 {
b.WriteString(":" + strconv.FormatInt(int64(uri.Port), 10))
b.WriteString(":" + portstr((uri.Port)))
}
uri.Params.Append(b)
}
// Returns true if scheme, host, and port match. if a username is present in
// `addr`, then the username is `other` must also match.
func (uri *URI) Compare(other *URI) bool {
func (uri *URI) CompareHostPort(other *URI) bool {
if uri != nil && other != nil {
if uri.Scheme == other.Scheme &&
uri.Host == other.Host &&
uri.Port == other.Port {
if uri.User != "" {
if uri.User == other.User {
return true
}
} else {
return true
}
if uri.Host == other.Host && uri.GetPort() == other.GetPort() {
return true
}
}
return false
}
func (uri *URI) GetPort() uint16 {
if uri.Port == 0 {
if uri.Scheme == "sips" {
return 5061
} else {
return 5060
}
} else {
return uri.Port
}
}
func (params Params) Copy() Params {
res := make(Params, len(params))
for k, v := range params {
@ -201,10 +202,7 @@ func (params Params) Append(b *bytes.Buffer) {
}
}
func (params *Params) Has(k string) bool {
if params == nil {
return false
}
_, ok := (*params)["lr"]
func (params Params) Has(k string) bool {
_, ok := params["lr"]
return ok
}

+ 29
- 45
sip/uri_test.go View File

@ -8,7 +8,6 @@ import (
type uriTest struct {
s string // user input we want to convert
s2 string // non-blank if 's' changes after we parse/format it
uri sip.URI // what 's' should become after parsing
err error // if we expect parsing to fail
}
@ -16,75 +15,67 @@ type uriTest struct {
var uriTests = []uriTest{
uriTest{
s: "sip:bsdtelecom.net",
s: "sip:google.com",
uri: sip.URI{
Scheme: "sip",
Host: "bsdtelecom.net",
Port: 5060,
Host: "google.com",
},
},
uriTest{
s: "sip:bsdtelecom.net:666",
s: "sip:jart@google.com",
uri: sip.URI{
Scheme: "sip",
Host: "bsdtelecom.net",
Port: 666,
User: "jart",
Host: "google.com",
},
},
uriTest{
s: "sip:jtunney@bsdtelecom.net",
s: "sip:jart@google.com:5060",
uri: sip.URI{
Scheme: "sip",
User: "jtunney",
Host: "bsdtelecom.net",
User: "jart",
Host: "google.com",
Port: 5060,
},
},
uriTest{
s: "sip:+12125650666@cat.lol",
s: "sip:google.com:666",
uri: sip.URI{
Scheme: "sip",
User: "+12125650666",
Host: "cat.lol",
Port: 5060,
Host: "google.com",
Port: 666,
},
},
uriTest{
s: "sip:jtunney@bsdtelecom.net:5060",
s2: "sip:jtunney@bsdtelecom.net",
s: "sip:+12125650666@cat.lol",
uri: sip.URI{
Scheme: "sip",
User: "jtunney",
Host: "bsdtelecom.net",
Port: 5060,
User: "+12125650666",
Host: "cat.lol",
},
},
uriTest{
s: "sip:jtunney:lawl@bsdtelecom.net:5060",
s2: "sip:jtunney:lawl@bsdtelecom.net",
s: "sip:jart:lawl@google.com",
uri: sip.URI{
Scheme: "sip",
User: "jtunney",
User: "jart",
Pass: "lawl",
Host: "bsdtelecom.net",
Port: 5060,
Host: "google.com",
},
},
uriTest{
s: "sip:jtunney:lawl@bsdtelecom.net:5060;isup-oli=00;omg;lol=cat",
s2: "sip:jtunney:lawl@bsdtelecom.net;isup-oli=00;omg;lol=cat",
s: "sip:jart:lawl@google.com;isup-oli=00;omg;lol=cat",
uri: sip.URI{
Scheme: "sip",
User: "jtunney",
User: "jart",
Pass: "lawl",
Host: "bsdtelecom.net",
Port: 5060,
Host: "google.com",
Params: sip.Params{
"isup-oli": "00",
"omg": "",
@ -94,12 +85,11 @@ var uriTests = []uriTest{
},
uriTest{
s: "sip:jtunney@bsdtelecom.net;isup-oli=00;omg;lol=cat",
s: "sip:jart@google.com;isup-oli=00;omg;lol=cat",
uri: sip.URI{
Scheme: "sip",
User: "jtunney",
Host: "bsdtelecom.net",
Port: 5060,
User: "jart",
Host: "google.com",
Params: sip.Params{
"isup-oli": "00",
"omg": "",
@ -113,15 +103,13 @@ var uriTests = []uriTest{
uri: sip.URI{
Scheme: "sip",
Host: "dead:beef::666",
Port: 5060,
},
},
uriTest{
s: "sip:[dead:beef::666]:5060",
s2: "sip:[dead:beef::666]",
s: "sips:[dead:beef::666]:5060",
uri: sip.URI{
Scheme: "sip",
Scheme: "sips",
Host: "dead:beef::666",
Port: 5060,
},
@ -155,13 +143,13 @@ var uriTests = []uriTest{
},
uriTest{
s: "sip:jtunney%3e:la%3ewl@bsdtelecom%3e.net:65535" +
s: "sip:jart%3e:la%3ewl@google%3e.net:65535" +
";isup%3e-oli=00%3e;%3eomg;omg;lol=cat",
uri: sip.URI{
Scheme: "sip",
User: "jtunney>",
User: "jart>",
Pass: "la>wl",
Host: "bsdtelecom>.net",
Host: "google>.net",
Port: 65535,
Params: sip.Params{
"isup>-oli": "00>",
@ -193,11 +181,7 @@ func TestParse(t *testing.T) {
func TestFormat(t *testing.T) {
for _, test := range uriTests {
uri := test.uri.String()
s := test.s
if test.s2 != "" {
s = test.s2
}
if s != uri {
if test.s != uri {
t.Error(test.s, "!=", uri)
}
}


+ 4
- 1
sip/util.go View File

@ -6,8 +6,11 @@ import (
"strings"
)
func portstr(port uint16) string {
return strconv.FormatInt(int64(port), 10)
}
func extractHostPort(s string) (s2, host string, port uint16, err error) {
port = 5060
if s == "" {
err = URIMissingHost
} else {


+ 1
- 6
sip/via.go View File

@ -117,12 +117,7 @@ func (via *Via) Last() *Via {
return via
}
// returns true if version, proto, ip, port, and branch match
func (via *Via) Compare(other *Via) bool {
return (via.CompareAddr(other) && via.CompareBranch(other))
}
func (via *Via) CompareAddr(other *Via) bool {
func (via *Via) CompareHostPort(other *Via) bool {
if via != nil && other != nil {
if via.Host == other.Host &&
via.Port == other.Port {


+ 0
- 11
util/util.go View File

@ -4,7 +4,6 @@ import (
"encoding/hex"
"math/rand"
"net"
"strconv"
"strings"
)
@ -49,16 +48,6 @@ func IsIPPrivate(ip net.IP) bool {
return false
}
func HostPortToString(host string, port uint16) (saddr string) {
sport := strconv.FormatInt(int64(port), 10)
if IsIPv6(host) {
saddr = "[" + host + "]:" + sport
} else {
saddr = host + ":" + sport
}
return saddr
}
// Generates a secure random number between 0 and 50,000.
func GenerateCSeq() int {
return rand.Int() % 50000


Loading…
Cancel
Save