Browse Source

Significantly msg_parse.go from 36k to 10k LOC.

pull/2/head
Justine Alexandra Roberts Tunney 11 years ago
parent
commit
248104a4b5
3 changed files with 6303 additions and 20776 deletions
  1. +6198
    -20559
      sip/msg_parse.go
  2. +88
    -216
      sip/msg_parse.rl
  3. +17
    -1
      sip/msg_test.go

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


+ 88
- 216
sip/msg_parse.rl View File

@ -32,6 +32,9 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
cs := 0
p := 0
pe := len(data)
//eof := len(data)
//stack := make([]int, 2)
//top := 0
line := 1
linep := 0
buf := make([]byte, len(data))
@ -39,8 +42,9 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
mark := 0
clen := 0
ctype := ""
// var b1 string
var b1 string
var hex byte
var dest *string
%%{
action break {
@ -103,51 +107,28 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
msg.Phrase = string(buf[0:amt])
}
action extHeaderName {
b1 = string(bytes.ToLower(data[mark:p]))
}
action extHeaderValue {
if msg.Headers == nil {
msg.Headers = Headers{}
}
msg.Headers[b1] = string(data[mark:p])
}
action Accept {
msg.Accept = string(data[mark:p])
}
action AcceptValue {
msg.AcceptContact = string(data[mark:p])
}
action AcceptEncoding {
msg.AcceptEncoding = string(data[mark:p])
action header {
fgoto header;
}
action AcceptLanguage {
msg.AcceptLanguage = string(data[mark:p])
}
action Allow {
msg.Allow = string(data[mark:p])
}
action AllowEvents {
msg.AllowEvents = string(data[mark:p])
}
action AlertInfo {
msg.AlertInfo = string(data[mark:p])
action hname {
b1 = string(bytes.ToLower(data[mark:p]))
}
action AuthenticationInfo {
msg.AuthenticationInfo = string(data[mark:p])
action svalue {
fhold;
fgoto svalue;
}
action Authorization {
msg.Authorization = string(data[mark:p])
action svalueDone {
if dest != nil {
*dest = string(data[mark:p - 1])
} else {
if msg.Headers == nil {
msg.Headers = Headers{}
}
msg.Headers[b1] = string(data[mark:p])
}
}
action CallID {
@ -160,22 +141,10 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
for *contactp != nil { contactp = &(*contactp).Next }
}
action ContentDisposition {
msg.ContentDisposition = string(data[mark:p])
}
action ContentLanguage {
msg.ContentLanguage = string(data[mark:p])
}
action ContentLength {
clen = clen * 10 + (int(fc) - 0x30)
}
action ContentEncoding {
msg.ContentEncoding = string(data[mark:p])
}
action ContentType {
ctype = string(data[mark:p])
}
@ -188,22 +157,6 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
msg.CSeqMethod = string(data[mark:p])
}
action CallInfo {
msg.CallInfo = string(data[mark:p])
}
action Date {
msg.Date = string(data[mark:p])
}
action ErrorInfo {
msg.ErrorInfo = string(data[mark:p])
}
action Event {
msg.Event = string(data[mark:p])
}
action Expires {
msg.Expires = msg.Expires * 10 + (int(fc) - 0x30)
}
@ -213,14 +166,6 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
if err != nil { return nil, err }
}
action InReplyTo {
msg.InReplyTo = string(data[mark:p])
}
action MaxForwardsZero {
msg.MaxForwards = 0
}
action MaxForwards {
msg.MaxForwards = msg.MaxForwards * 10 + (int(fc) - 0x30)
}
@ -229,115 +174,39 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
msg.MinExpires = msg.MinExpires * 10 + (int(fc) - 0x30)
}
action ReplyTo {
msg.ReplyTo = string(data[mark:p])
}
action MIMEVersion {
msg.MIMEVersion = string(data[mark:p])
}
action Organization {
msg.Organization = string(data[mark:p])
}
action PAssertedIdentity {
msg.PAssertedIdentity, err = ParseAddr(string(data[mark:p]))
if err != nil { return nil, err }
}
action Priority {
msg.Priority = string(data[mark:p])
}
action ProxyAuthenticate {
msg.ProxyAuthenticate = string(data[mark:p])
}
action ProxyAuthorization {
msg.ProxyAuthorization = string(data[mark:p])
}
action ProxyRequire {
msg.ProxyRequire = string(data[mark:p])
}
action RecordRoute {
*rroutep, err = ParseAddr(string(data[mark:p]))
if err != nil { return nil, err }
for *rroutep != nil { rroutep = &(*rroutep).Next }
}
action ReferTo {
msg.ReferTo = string(data[mark:p])
}
action ReferredBy {
msg.ReferredBy = string(data[mark:p])
}
action RemotePartyID {
msg.RemotePartyID, err = ParseAddr(string(data[mark:p]))
if err != nil { return nil, err }
}
action Require {
msg.Require = string(data[mark:p])
}
action RetryAfter {
msg.RetryAfter = string(data[mark:p])
}
action Route {
*routep, err = ParseAddr(string(data[mark:p]))
if err != nil { return nil, err }
for *routep != nil { routep = &(*routep).Next }
}
action Server {
msg.Server = string(data[mark:p])
}
action Subject {
msg.Subject = string(data[mark:p])
}
action Supported {
msg.Supported = string(data[mark:p])
}
action Timestamp {
msg.Timestamp = string(data[mark:p])
}
action To {
msg.To, err = ParseAddr(string(data[mark:p]))
if err != nil { return nil, err }
}
action Unsupported {
msg.Unsupported = string(data[mark:p])
}
action UserAgent {
msg.UserAgent = string(data[mark:p])
}
action Via {
*viap, err = ParseVia(string(data[mark:p]))
if err != nil { return nil, err }
for *viap != nil { viap = &(*viap).Next }
}
action Warning {
msg.Warning = string(data[mark:p])
}
action WWWAuthenticate {
msg.WWWAuthenticate = string(data[mark:p])
}
action lookAheadWSP { p + 2 < pe && (data[p+2] == ' ' || data[p+2] == '\t') }
# https://tools.ietf.org/html/rfc2234
@ -357,10 +226,8 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," ;
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" ;
unreserved = alpha | digit | mark ;
HCOLON = WSP* ":" SWS ;
tokenc = alpha | digit | "-" | "." | "!" | "%" | "*" | "_"
| "+" | "`" | "'" | "~" ;
token = tokenc+ >mark ;
separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\"
| "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP
| HTAB ;
@ -378,6 +245,7 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
COMMA = SWS "," SWS ;
SEMI = SWS ";" SWS ;
COLON = SWS ":" SWS ;
HCOLON = WSP* ":" SWS ;
LDQUOT = SWS "\"" ;
RDQUOT = "\"" SWS ;
ctext = 0x21..0x27 | 0x2A..0x5B | 0x5D..0x7E | UTF8_NONASCII | LWS ;
@ -389,6 +257,7 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
uric = reserved | unreserved | escaped ;
uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | "&" | "="
| "+" | "$" | "," ;
token = tokenc+ >mark ;
reasonc = reserved | unreserved | UTF8_NONASCII | SP | HTAB ;
reasonmc = escaped | ( reasonc @append ) ;
cid = word ( "@" word )? ;
@ -399,69 +268,72 @@ func ParseMsgBytes(data []byte) (msg *Msg, err error) {
StatusCode = ( digit @StatusCode ) {3};
ReasonPhrase = reasonmc+ >start %ReasonPhrase;
hval = ( UTF8 | LWS )* >mark;
extHeader = token %extHeaderName HCOLON hval %extHeaderValue;
# http://www.iana.org/assignments/sip-parameters/sip-parameters.xhtml
stdHeader = "Accept"i HCOLON hval %Accept
| ("Accept-Contact"i | "a"i) HCOLON hval %AcceptValue
| "Accept-Encoding"i HCOLON hval %AcceptEncoding
| "Accept-Language"i HCOLON hval %AcceptLanguage
| ("Allow"i | "u"i) HCOLON hval %Allow
| ("Allow-Events"i | "u"i) HCOLON hval %AllowEvents
| "Alert-Info"i HCOLON hval %AlertInfo
| "Authentication-Info"i HCOLON hval %AuthenticationInfo
| "Authorization"i HCOLON hval %Authorization
| ("Call-ID"i | "i"i) HCOLON cid >mark %CallID
| ("Contact"i | "m"i) HCOLON hval %Contact
| "Content-Disposition"i HCOLON hval %ContentDisposition
| "Content-Language"i HCOLON hval %ContentLanguage
| ("Content-Length"i | "l"i) HCOLON digit+ @ContentLength
| ("Content-Encoding"i | "e"i) HCOLON hval %ContentEncoding
| ("Content-Type"i | "c"i) HCOLON hval %ContentType
| "CSeq"i HCOLON (digit+ @CSeq) LWS token >mark %CSeqMethod
| "Call-Info"i HCOLON hval %CallInfo
| "Date"i HCOLON hval %Date
| "Error-Info"i HCOLON hval %ErrorInfo
| ("Event"i | "o"i) HCOLON hval %Event
| ("Expires"i | "l"i) HCOLON digit+ @Expires
| ("From"i | "f"i) HCOLON hval %From
| "In-Reply-To"i HCOLON hval %InReplyTo
| ("Max-Forwards"i | "l"i) HCOLON digit+ >MaxForwardsZero @MaxForwards
| ("Min-Expires"i | "l"i) HCOLON digit+ @MinExpires
| "Reply-To"i HCOLON hval %ReplyTo
| "MIME-Version"i HCOLON hval %MIMEVersion
| "Organization"i HCOLON hval %Organization
| "P-Asserted-Identity"i HCOLON hval %PAssertedIdentity
| "Priority"i HCOLON hval %Priority
| "Proxy-Authenticate"i HCOLON hval %ProxyAuthenticate
| "Proxy-Authorization"i HCOLON hval %ProxyAuthorization
| "Proxy-Require"i HCOLON hval %ProxyRequire
| "Record-Route"i HCOLON hval %RecordRoute
| ("Refer-To"i | "r"i) HCOLON hval %ReferTo
| ("Referred-By"i | "b"i) HCOLON hval %ReferredBy
| "Remote-Party-ID"i HCOLON hval %RemotePartyID
| "Require"i HCOLON hval %Require
| "Retry-After"i HCOLON hval %RetryAfter
| "Route"i HCOLON hval %Route
| "Server"i HCOLON hval %Server
| ("Subject"i | "s"i) HCOLON hval %Subject
| ("Supported"i | "k"i) HCOLON hval %Supported
| "Timestamp"i HCOLON hval %Timestamp
| ("To"i | "t"i) HCOLON hval %To
| "Unsupported"i HCOLON hval %Unsupported
| "User-Agent"i HCOLON hval %UserAgent
| ("Via"i | "v"i) HCOLON hval %Via
| "Warning"i HCOLON hval %Warning
| "WWW-Authenticate"i HCOLON hval %WWWAuthenticate
;
header = stdHeader CRLF;
headers = header* CR LF @break;
cheader = ("Call-ID"i | "i"i) HCOLON cid >mark %CallID
| ("Contact"i | "m"i) HCOLON <: hval %Contact
| ("Content-Length"i | "l"i) HCOLON digit+ >{clen=0} @ContentLength
| ("Content-Type"i | "c"i) HCOLON <: hval %ContentType
| "CSeq"i HCOLON (digit+ @CSeq) LWS token %CSeqMethod
| ("Expires"i | "l"i) HCOLON digit+ >{msg.Expires=0} @Expires
| ("From"i | "f"i) HCOLON <: hval %From
| ("Max-Forwards"i | "l"i) HCOLON digit+ >{msg.MaxForwards=0} @MaxForwards
| ("Min-Expires"i | "l"i) HCOLON digit+ >{msg.MinExpires=0} @MinExpires
| "P-Asserted-Identity"i HCOLON <: hval %PAssertedIdentity
| "Record-Route"i HCOLON <: hval %RecordRoute
| "Remote-Party-ID"i HCOLON <: hval %RemotePartyID
| "Route"i HCOLON <: hval %Route
| ("To"i | "t"i) HCOLON <: hval %To
| ("Via"i | "v"i) HCOLON <: hval %Via
;
sname = "Accept"i %{dest=&msg.Accept}
| ("Accept-Contact"i | "a"i) %{dest=&msg.AcceptContact}
| "Accept-Encoding"i %{dest=&msg.AcceptEncoding}
| "Accept-Language"i %{dest=&msg.AcceptLanguage}
| ("Allow"i | "u"i) %{dest=&msg.Allow}
| ("Allow-Events"i | "u"i) %{dest=&msg.AllowEvents}
| "Alert-Info"i %{dest=&msg.AlertInfo}
| "Authentication-Info"i %{dest=&msg.AuthenticationInfo}
| "Authorization"i %{dest=&msg.Authorization}
| "Content-Disposition"i %{dest=&msg.ContentDisposition}
| "Content-Language"i %{dest=&msg.ContentLanguage}
| ("Content-Encoding"i | "e"i) %{dest=&msg.ContentEncoding}
| "Call-Info"i %{dest=&msg.CallInfo}
| "Date"i %{dest=&msg.Date}
| "Error-Info"i %{dest=&msg.ErrorInfo}
| ("Event"i | "o"i) %{dest=&msg.Event}
| "In-Reply-To"i %{dest=&msg.InReplyTo}
| "Reply-To"i %{dest=&msg.ReplyTo}
| "MIME-Version"i %{dest=&msg.MIMEVersion}
| "Organization"i %{dest=&msg.Organization}
| "Priority"i %{dest=&msg.Priority}
| "Proxy-Authenticate"i %{dest=&msg.ProxyAuthenticate}
| "Proxy-Authorization"i %{dest=&msg.ProxyAuthorization}
| "Proxy-Require"i %{dest=&msg.ProxyRequire}
| ("Refer-To"i | "r"i) %{dest=&msg.ReferTo}
| ("Referred-By"i | "b"i) %{dest=&msg.ReferredBy}
| "Require"i %{dest=&msg.Require}
| "Retry-After"i %{dest=&msg.RetryAfter}
| "Server"i %{dest=&msg.Server}
| ("Subject"i | "s"i) %{dest=&msg.Subject}
| ("Supported"i | "k"i) %{dest=&msg.Supported}
| "Timestamp"i %{dest=&msg.Timestamp}
| "Unsupported"i %{dest=&msg.Unsupported}
| "User-Agent"i %{dest=&msg.UserAgent}
| "Warning"i %{dest=&msg.Warning}
| "WWW-Authenticate"i %{dest=&msg.WWWAuthenticate}
;
svalue := hval CR LF @svalueDone @header;
xheader = token %hname HCOLON @{dest=nil} @svalue;
header := CR LF @break
| sname HCOLON <: any @svalue
| cheader CR LF @header
;
SIPVersion = "SIP/" SIPVersionNo;
RequestLine = Method SP RequestURI SP SIPVersion CRLF;
StatusLine = SIPVersion SP StatusCode SP ReasonPhrase CRLF;
Request = RequestLine headers;
Response = StatusLine headers;
Request = Method SP RequestURI SP SIPVersion CR LF @header;
Response = SIPVersion SP StatusCode SP ReasonPhrase CR LF @header;
main := Request | Response;
write init;


+ 17
- 1
sip/msg_test.go View File

@ -15,6 +15,22 @@ type msgTest struct {
var msgTests = []msgTest{
msgTest{
name: "Digit Padding",
s: "OPTIONS sip:10.11.34.37 SIP/2.0\r\n" +
"Expires: 666\r\n" +
"\r\n",
msg: sip.Msg{
VersionMajor: 2,
Method: "OPTIONS",
Expires: 666,
Request: &sip.URI{
Scheme: "sip",
Host: "10.11.34.37",
},
},
},
msgTest{
name: "OPTIONS",
s: "OPTIONS sip:10.11.34.37:42367 SIP/2.0\r\n" +
@ -368,7 +384,7 @@ func TestParseMsg(t *testing.T) {
}
}
if !reflect.DeepEqual(&test.msg, msg) {
t.Errorf("Message:\n%#v !=\n%#v", &test.msg, msg)
t.Errorf("%s:\n%#v !=\n%#v", test.name, &test.msg, msg)
if !reflect.DeepEqual(test.msg.Payload, msg.Payload) {
t.Errorf("Payload:\n%#v !=\n%#v", test.msg.Payload, msg.Payload)
}


Loading…
Cancel
Save