Browse Source

Remove old ParseAddr() implementation.

pull/2/head
Justine Alexandra Roberts Tunney 11 years ago
parent
commit
ee650f50da
6 changed files with 3321 additions and 3953 deletions
  1. +20
    -6
      sip/addr.go
  2. +0
    -2779
      sip/addr_parse.go
  3. +0
    -214
      sip/addr_parse.rl
  4. +3297
    -950
      sip/msg_parse.go
  5. +1
    -1
      sip/msg_parse.rl
  6. +3
    -3
      sip/uri.go

+ 20
- 6
sip/addr.go View File

@ -2,16 +2,16 @@
//
// For example:
//
// "J.A. Roberts Tunney" <sip:jtunney@bsdtelecom.net;isup-oli=29>;tag=deadbeef
// "Justine Tunney" <sip:jart@example.test;isup-oli=29>;tag=feedabee
//
// Roughly equates to:
//
// {Display: "J.A. Roberts Tunney",
// Params: {"tag": "deadbeef"},
// {Display: "Justine Tunney",
// Params: {"tag": "feedabee"},
// Uri: {Scheme: "sip",
// User: "jtunney",
// User: "jart",
// Pass: "",
// Host: "bsdtelecom.net",
// Host: "example.test",
// Port: "",
// Params: {"isup-oli": "29"}}}
//
@ -31,7 +31,21 @@ type Addr struct {
Next *Addr // for comma separated lists of addresses
}
//go:generate ragel -Z -G2 -o addr_parse.go addr_parse.rl
func ParseAddr(s string) (addr *Addr, err error) {
return ParseAddrBytes([]byte(s))
}
func ParseAddrBytes(s []byte) (addr *Addr, err error) {
var b bytes.Buffer
b.WriteString("SIP/2.0 900 ParseAddr()\r\nContact:")
b.Write(s)
b.WriteString("\r\n\r\n")
msg, err := ParseMsgBytes(b.Bytes())
if err != nil {
return nil, err
}
return msg.Contact, nil
}
func (addr *Addr) String() string {
if addr == nil {


+ 0
- 2779
sip/addr_parse.go
File diff suppressed because it is too large
View File


+ 0
- 214
sip/addr_parse.rl View File

@ -1,214 +0,0 @@
// -*-go-*-
package sip
import (
"errors"
"fmt"
"strings"
)
%% machine addr;
%% write data;
// ParseAddr turns a SIP address into a data structure.
func ParseAddr(s string) (addr *Addr, err error) {
if s == "" {
return nil, errors.New("Empty SIP message")
}
return ParseAddrBytes([]byte(s), nil)
}
// ParseAddr turns a SIP address slice into a data structure.
func ParseAddrBytes(data []byte, next *Addr) (addr *Addr, err error) {
if data == nil {
return nil, nil
}
addr = new(Addr)
result := addr
cs := 0
p := 0
pe := len(data)
eof := len(data)
buf := make([]byte, len(data))
amt := 0
mark := 0
var name string
%%{
action mark {
mark = p
}
action start {
amt = 0
}
action append {
buf[amt] = fc
amt++
}
action name {
name = string(data[mark:p])
}
action display {
// TODO: Collapse this string.
addr.Display = strings.TrimRight(string(buf[0:amt]), " \t\r\n")
}
action qdisplay {
addr.Display = string(buf[0:amt])
}
action uri {
addr.Uri, err = ParseURIBytes(data[mark:p])
if err != nil { return nil, err }
}
action param {
if addr.Params == nil {
addr.Params = Params{}
}
addr.Params[name] = string(buf[0:amt])
}
action lookAheadWSP { p + 2 < pe && (data[p+2] == ' ' || data[p+2] == '\t') }
action goto_name_addr {
p = mark
fhold;
fgoto name_addr;
}
action goto_bare_addr {
p = mark
fhold;
fgoto bare_addr;
}
action goto_params {
fhold;
fgoto params;
}
action goto_addr {
addr.Next = new(Addr)
addr = addr.Next
fhold;
fgoto addr;
}
# https://tools.ietf.org/html/rfc2234
SP = " ";
HTAB = "\t";
CR = "\r";
LF = "\n";
DQUOTE = "\"";
CRLF = CR LF;
WSP = SP | HTAB;
LWS = ( WSP* ( CR when lookAheadWSP ) LF )? WSP+;
SWS = LWS?;
UTF8_CONT = 0x80..0xBF @append;
UTF8_NONASCII = 0xC0..0xDF @append UTF8_CONT {1}
| 0xE0..0xEF @append UTF8_CONT {2}
| 0xF0..0xF7 @append UTF8_CONT {3}
| 0xF8..0xFb @append UTF8_CONT {4}
| 0xFC..0xFD @append UTF8_CONT {5};
UTF8 = 0x21..0x7F @append | UTF8_NONASCII;
LWSCRLF_append = ( CR when lookAheadWSP ) @append LF @append;
LWS_append = ( WSP* @append LWSCRLF_append )? WSP+ @append;
# https://tools.ietf.org/html/rfc3261#section-25.1
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," ;
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" ;
unreserved = alnum | mark ;
tokenc = alnum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`"
| "'" | "~" ;
separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\"
| "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP
| HTAB ;
wordc = alnum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`"
| "'" | "~" | "(" | ")" | "<" | ">" | ":" | "\\" | "\""
| "/" | "[" | "]" | "?" | "{" | "}" ;
word = wordc+;
STAR = SWS "*" SWS;
SLASH = SWS "/" SWS;
EQUAL = SWS "=" SWS;
LPAREN = SWS "(" SWS;
RPAREN = SWS ")" SWS;
RAQUOT = ">" SWS;
LAQUOT = SWS "<";
COMMA = SWS "," SWS;
SEMI = SWS ";" SWS;
COLON = SWS ":" SWS;
HCOLON = WSP* ":" SWS;
LDQUOT = SWS "\"";
RDQUOT = "\"" SWS;
# The RFC BNF for SIP addresses is a bit nuts; we'll try our best.
token = tokenc+;
tokenhost = ( tokenc | "[" | "]" | ":" )+;
schemec = alnum | "+" | "-" | ".";
scheme = alpha schemec*;
uric = reserved | unreserved | "%" | "[" | "]";
uri = scheme ":" uric+;
# Quoted strings can have just about anything, including backslash escapes,
# which aren't quite as fancy as the ones you'd see in programming.
qdtextc = 0x21 | 0x23..0x5B | 0x5D..0x7E;
qdtext = UTF8_NONASCII | LWS_append | qdtextc @append;
quoted_pair = "\\" ( 0x00..0x09 | 0x0B..0x0C | 0x0E..0x7F ) @append;
quoted_content = ( qdtext | quoted_pair )* >start;
quoted_string = SWS DQUOTE quoted_content DQUOTE;
# The display name can either be quoted or unquoted. The unquoted form is
# much more limited in what it may contain, although it does permit spaces.
display_name = quoted_string %qdisplay
| SWS ( token @append LWS_append )* >start %display
;
# Parameter parsing is pretty straightforward. Unlike URI parameters, the
# values on these can be quoted. The only thing that's weird is if the URI
# doesn't appear in angle brackets, the parameters need to be owned by the
# Addr object, not the URI. This has been placed in its own machine so it
# doesn't have to be duplicated in the two machines below.
param_name = token >mark >start %name;
param_content = tokenhost @append;
param_value = param_content | quoted_string;
param = ( param_name ( EQUAL param_value )? ) %param;
params := ( SEMI param )* ( COMMA <: any @goto_addr )?;
# Now we're going to define two separate machines. The first is for
# addresses with angle brackets and the second is for ones without.
addr_spec = uri >mark %uri;
name_addr := display_name? LAQUOT addr_spec RAQUOT <: ( any @goto_params )?;
bare_addr := ( addr_spec -- ";" ) <: ( any @goto_params )?;
# Now we perform lookahead to determine which machine we should use.
look = [^;<]
| ";" @goto_bare_addr
| "<" @goto_name_addr
;
addr := look+ >mark $eof(goto_name_addr);
write init;
write exec;
}%%
if cs < addr_first_final {
if p == pe {
return nil, errors.New(fmt.Sprintf("Incomplete SIP address: %s", data))
} else {
return nil, errors.New(fmt.Sprintf("Error in SIP address at offset %d: %s", p, string(data)))
}
}
if next != nil {
next.Last().Next = result
return next, nil
}
return result, nil
}

+ 3297
- 950
sip/msg_parse.go
File diff suppressed because it is too large
View File


+ 1
- 1
sip/msg_parse.rl View File

@ -45,7 +45,7 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
%% main := Message;
%% write init;
%% write exec noend;
%% write exec;
if cs < msg_first_final {
if p == pe {


+ 3
- 3
sip/uri.go View File

@ -6,14 +6,14 @@
//
// For example:
//
// jtunney@bsdtelecom.net;isup-oli=29
// jart@example.test;isup-oli=29
//
// Roughly equates to:
//
// {Scheme: "sip",
// User: "jtunney",
// User: "jart",
// Pass: "",
// Host: "bsdtelecom.net",
// Host: "example.test",
// Port: "",
// Params: {"isup-oli": "29"}}
//


Loading…
Cancel
Save