; The following rules are used throughout this specification to
;   describe basic parsing constructs.  The US-ASCII coded character set
;   is defined by ANSI X3.4-1986.

alphanum  =  ALPHA / DIGIT

;   Several rules are incorporated from RFC 2396 [5] but are updated to
;   make them compliant with RFC 2234 [10].  These include:

reserved    =  ";" / "/" / "?" / ":" / "@" / "&" / "=" / "+"
                     / "$" / ","
unreserved  =  alphanum / mark

mark        =  "-" / "_" / "." / "!" / "~" / "*" / "'"
                     / "(" / ")"

escaped     =  "%" HEXDIG HEXDIG

;   SIP header field values can be folded onto multiple lines if the
;   continuation line begins with a space or horizontal tab.  All linear
;   white space, including folding, has the same semantics as SP.  A
;   recipient MAY replace any linear white space with a single SP before
;   interpreting the field value or forwarding the message downstream.
;   This is intended to behave exactly as HTTP/1.1 as described in RFC
;   2616 [8].  The SWS construct is used when linear white space is
;   optional, generally between tokens and separators.

LWS  =  [*WSP CRLF] 1*WSP  : 'LWS'.

SWS  =  [LWS]  : 'SWS'.

;   To separate the header name from the rest of value, a colon is used,
;   which, by the above rule, allows whitespace before, but no line
;   break, and whitespace after, including a linebreak.  The HCOLON
;   defines this construct.

HCOLON  =  *( SP / HTAB ) ":" SWS : 'HCOLON'.

;   The TEXT-UTF8 rule is only used for descriptive field contents and
;   values that are not intended to be interpreted by the message parser.
;   Words of *TEXT-UTF8 contain characters from the UTF-8 charset (RFC
;   2279 [7]).  The TEXT-UTF8-TRIM rule is used for descriptive field
;   contents that are n t quoted strings, where leading and trailing LWS
;   is not meaningful.  In this regard, SIP differs from HTTP, which uses
;   the ISO 8859-1 character set.

TEXT-UTF8-TRIM  =  1*TEXT-UTF8char *(*LWS TEXT-UTF8char)

TEXT-UTF8char   =  %x21-7E / UTF8-NONASCII

UTF8-NONASCII   =  %xC0-DF 1UTF8-CONT
                      /  %xE0-EF 2UTF8-CONT
                      /  %xF0-F7 3UTF8-CONT
                      /  %xF8-FB 4UTF8-CONT
                      /  %xFC-FD 5UTF8-CONT

UTF8-CONT       =  %x80-BF

;   A CRLF is allowed in the definition of TEXT-UTF8-TRIM only as part of
;   a header field continuation.  It is expected that the folding LWS
;   will be replaced with a single SP before interpretation of the TEXT-
;   UTF8-TRIM value.

;   Hexadecimal numeric characters are used in several protocol elements.
;   Some elements (authentication) force hex alphas to be lower case.

LHEX  =  DIGIT / %x61-66 ;lowercase a-f

;   Many SIP header field values consist of words separated by LWS or
;   special characters.  Unless otherwise stated, tokens are case-
;   insensitive.  These special characters MUST be in a quoted string to
;   be used within a parameter value.  The word construct is used in
;   Call-ID to allow most separators to be used.

token       =  1*(alphanum / "-" / "." / "!" / "%" / "*"
                     / "_" / "+" / "`" / "'" / "~" )

separators  =  "(" / ")" / "<" / ">" / "@" /
                     "," / ";" / ":" / "\" / DQUOTE /
                     "/" / "[" / "]" / "?" / "=" /
                     "{" / "}" / SP / HTAB

word        =  1*(alphanum / "-" / "." / "!" / "%" / "*" /
                     "_" / "+" / "`" / "'" / "~" /
                     "(" / ")" / "<" / ">" /
                     ":" / "\" / DQUOTE /
                     "/" / "[" / "]" / "?" /
                     "{" / "}" )

;   When tokens are used or separators are used between elements,
;   whitespace is often allowed before or after these characters:

STAR    =  SWS "*" SWS : 'STAR'.

SLASH   =  SWS "/" SWS : 'SLASH'.

EQUAL   =  SWS "=" SWS : 'EQUAL'.

LPAREN  =  SWS "(" SWS : 'LPAREN'.

RPAREN  =  SWS ")" SWS : 'RPAREN'.

RAQUOT  =  ">" SWS : 'RAQUOT'.

LAQUOT  =  SWS "<" : 'LAQUOT'.

COMMA   =  SWS "," SWS : 'COMMA'.

SEMI    =  SWS ";" SWS : 'SEMI'.

COLON   =  SWS ":" SWS : 'COLON'.

LDQUOT  =  SWS DQUOTE : 'LDQUOT'.

RDQUOT  =  DQUOTE SWS : 'RDQUOT'.

;   Comments can be included in some SIP header fields by surrounding the
;   comment text with parentheses.  Comments are only allowed in fields
;   containing "comment" as part of their field value definition.  In all
;   other fields, parentheses are considered part of the field value.

comment  =  LPAREN *(ctext / quoted-pair / comment) RPAREN

ctext    =  %x21-27 / %x2A-5B / %x5D-7E / UTF8-NONASCII
                  / LWS

;   ctext includes all chars except left and right parens and backslash.
;   A string of text is parsed as a single word if it is quoted using
;   double-quote marks.  In quoted strings, quotation marks (") and
;   backslashes (\) need to be escaped.

quoted-string  =  SWS DQUOTE *(qdtext / quoted-pair ) DQUOTE : _YY3.

qdtext         =  LWS / %x21 / %x23-5B / %x5D-7E
                        / UTF8-NONASCII

;   The backslash character ("\") MAY be used as a single-character
;   quoting mechanism only within quoted-string and comment constructs.
;   Unlike HTTP/1.1, the characters CR and LF cannot be escaped by this
;   mechanism to avoid conflict with line folding and header separation.

quoted-pair  =  "\" (%x00-09 / %x0B-0C
                / %x0E-7F)

SIP-URI          =  "sip:" [ userinfo ] hostport
                    uri-parameters [ headers ] : {'SIP-URI', _YY2, _YY3, _YY4, _YY5}.

SIPS-URI         =  "sips:" [ userinfo ] hostport
                    uri-parameters [ headers ]

userinfo         =  ( user / telephone-subscriber ) [ ":" password ] "@" : {userinfo, _YY1, _YY2}.

user             =  1*( unreserved / escaped / user-unreserved ) : {user, lists:flatten(_YY)}.

user-unreserved  =  "&" / "=" / "+" / "$" / "," / ";" / "?" / "/"

password         =  *( unreserved / escaped /
                    "&" / "=" / "+" / "$" / "," )

hostport         =  host [ ":" port ] : {hostport, _YY1, case _YY2 of [] -> []; [[_, Port]] -> list_to_integer(Port) end}.

host             =  hostname / IPv4address / IPv6reference

hostname         =  *( domainlabel "." ) toplabel [ "." ] : lists:flatten(_YY).

domainlabel      =  *( alphanum / "-" )
; This should really be 
;(alphanum *( alphanum / "-" ) alphanum) /
;		    alphanum

toplabel         =  *( alphanum / "-" )
;this should really be
;ALPHA / ALPHA *( alphanum / "-" ) alphanum

IPv4address    =  1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT

IPv6reference  =  "[" IPv6address "]"

IPv6address    =  hexpart [ ":" IPv4address ]

hexpart        =  hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ]

hexseq         =  hex4 *( ":" hex4)

hex4           =  1*4HEXDIG

port           =  1*DIGIT

;   The BNF for telephone-subscriber can be found in RFC 2806 [9].  Note,
;   however, that any characters allowed there that are not allowed in
;   the user part of the SIP URI MUST be escaped.

uri-parameters    =  *( ";" uri-parameter) : {'uri-parameters', [P || [$;,P] <- _YY]}.

uri-parameter     =  transport-param / user-param / method-param
                     / ttl-param / maddr-param / lr-param / other-param

transport-param   =  "transport="
                     ( "udp" / "tcp" / "sctp" / "tls"
                     / other-transport) : {transport, _YY2}.

other-transport   =  token

user-param        =  "user=" ( "phone" / "ip" / other-user) : {'user-param', _YY2}.

other-user        =  token

method-param      =  "method=" Method : {'method-param', _YY2}.

ttl-param         =  "ttl=" ttl : {'ttl-param', _YY2}.

maddr-param       =  "maddr=" host : {'maddr-param', _YY2}.

lr-param          =  "lr" : lr.

other-param       =  pname [ "=" pvalue ] : 
case _YY2 of
    [[_,Val]] -> 
        {'other-param', _YY1, Val};
    [] -> {'other-param', _YY1}
end.

pname             =  1*paramchar

pvalue            =  1*paramchar

paramchar         =  param-unreserved / unreserved / escaped

param-unreserved  =  "[" / "]" / "/" / ":" / "&" / "+" / "$"

headers         =  "?" header *( "&" header )

header          =  hname "=" hvalue

hname           =  1*( hnv-unreserved / unreserved / escaped )

hvalue          =  *( hnv-unreserved / unreserved / escaped )

hnv-unreserved  =  "[" / "]" / "/" / "?" / ":" / "+" / "$"

SIP-message    =  Request / Response

Request        =  Request-Line
                  *( message-header )
                  CRLF              : {'Request', _YY1, _YY2}.
;                  [ message-body ] : {'Request', _YY1, _YY2, _YY4}.

Request-Line   =  Method SP Request-URI SP SIP-Version CRLF :
    {'Request-Line', _YY1, _YY3, _YY5}.

Request-URI    =  SIP-URI / SIPS-URI / absoluteURI

absoluteURI    =  scheme ":" ( hier-part / opaque-part )

hier-part      =  ( net-path / abs-path ) [ "?" query ]

net-path       =  "//" authority [ abs-path ]

abs-path       =  "/" path-segments

opaque-part    =  uric-no-slash *uric

uric           =  reserved / unreserved / escaped

uric-no-slash  =  unreserved / escaped / ";" / "?" / ":" / "@"
                  / "&" / "=" / "+" / "$" / ","

path-segments  =  segment *( "/" segment )

segment        =  *pchar *( ";" param )

param          =  *pchar

pchar          =  unreserved / escaped /
                  ":" / "@" / "&" / "=" / "+" / "$" / ","

scheme         =  ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

authority      =  srvr / reg-name

srvr           =  [ [ userinfo "@" ] hostport ]

reg-name       =  1*( unreserved / escaped / "$" / ","
                  / ";" / ":" / "@" / "&" / "=" / "+" )

query          =  *uric

SIP-Version    =  "SIP" "/" 1*DIGIT "." 1*DIGIT :
{'SIP-Version', _YY3++[_YY4]++ _YY5}.

message-header  =  (Accept
                /  Accept-Encoding
                /  Accept-Language
                /  Alert-Info
                /  Allow
                /  Authentication-Info
 ;                /  Authorization
                /  Call-ID
                /  Call-Info
                /  Contact
                /  Content-Disposition
                /  Content-Encoding
                /  Content-Language
                /  Content-Length
                /  Content-Type
                /  CSeq
                /  Date
                /  Error-Info
                /  Expires
                /  From
                /  In-Reply-To
                /  Max-Forwards
                /  MIME-Version
                /  Min-Expires
                /  Organization
                /  Priority
                /  Proxy-Authenticate
 ;                /  Proxy-Authorization
                /  Proxy-Require
                /  Record-Route
                /  Reply-To
                /  Require
                /  Retry-After
                /  Route
                /  Server
                /  Subject
                /  Supported
                /  Timestamp
                /  To
                /  Unsupported
                /  User-Agent
                /  Via
                /  Warning
                /  WWW-Authenticate
                /  extension-header) CRLF : _YY1.

INVITEm           =  %x49.4E.56.49.54.45 
; INVITE in caps

ACKm              =  %x41.43.4B 
; ACK in caps

OPTIONSm          =  %x4F.50.54.49.4F.4E.53 
; OPTIONS in caps

BYEm              =  %x42.59.45 
; BYE in caps

CANCELm           =  %x43.41.4E.43.45.4C 
; CANCEL in caps

REGISTERm         =  %x52.45.47.49.53.54.45.52 
; REGISTER in caps

Method            =  INVITEm / ACKm / OPTIONSm / BYEm
                     / CANCELm / REGISTERm
                     / extension-method

extension-method  =  token

Response          =  Status-Line
                     *( message-header )
                     CRLF        : {'Response',_YY1,_YY2}.
;                     [ message-body ]

Status-Line     =  SIP-Version SP Status-Code SP Reason-Phrase CRLF:
{'Status-Line',_YY1,_YY3,_YY5}.

Status-Code     =  Informational
               /   Redirection
               /   Success
               /   Client-Error
               /   Server-Error
               /   Global-Failure
               /   extension-code

extension-code  =  3DIGIT

Reason-Phrase   =  *(reserved / unreserved / escaped
                   / UTF8-NONASCII / UTF8-CONT / SP / HTAB)

Informational  =  "100"  ;  Trying
              /   "180"  ;  Ringing
              /   "181"  ;  Call Is Being Forwarded
              /   "182"  ;  Queued
              /   "183"  ;  Session Progress

Success  =  "200"  ;  OK

Redirection  =  "300"  ;  Multiple Choices
            /   "301"  ;  Moved Permanently
            /   "302"  ;  Moved Temporarily
            /   "305"  ;  Use Proxy
            /   "380"  ;  Alternative Service

Client-Error  =  "400"  ;  Bad Request
             /   "401"  ;  Unauthorized
             /   "402"  ;  Payment Required
             /   "403"  ;  Forbidden
             /   "404"  ;  Not Found
             /   "405"  ;  Method Not Allowed
             /   "406"  ;  Not Acceptable
             /   "407"  ;  Proxy Authentication Required
             /   "408"  ;  Request Timeout
             /   "410"  ;  Gone
             /   "413"  ;  Request Entity Too Large
             /   "414"  ;  Request-URI Too Large
             /   "415"  ;  Unsupported Media Type
             /   "416"  ;  Unsupported URI Scheme
             /   "420"  ;  Bad Extension
             /   "421"  ;  Extension Required
             /   "423"  ;  Interval Too Brief
             /   "480"  ;  Temporarily not available
             /   "481"  ;  Call Leg/Transaction Does Not Exist
             /   "482"  ;  Loop Detected
             /   "483"  ;  Too Many Hops
             /   "484"  ;  Address Incomplete
             /   "485"  ;  Ambiguous
             /   "486"  ;  Busy Here
             /   "487"  ;  Request Terminated
             /   "488"  ;  Not Acceptable Here
             /   "491"  ;  Request Pending
             /   "493"  ;  Undecipherable

Server-Error  =  "500"  ;  Internal Server Error
             /   "501"  ;  Not Implemented
             /   "502"  ;  Bad Gateway
             /   "503"  ;  Service Unavailable
             /   "504"  ;  Server Time-out
             /   "505"  ;  SIP Version not supported
             /   "513"  ;  Message Too Large

Global-Failure  =  "600"  ;  Busy Everywhere
               /   "603"  ;  Decline
               /   "604"  ;  Does not exist anywhere
               /   "606"  ;  Not Acceptable

Accept         =  "Accept" HCOLON
                   [ accept-range *(COMMA accept-range) ] :
    Accept = case _YY3 of
    	         [] -> [];
		 [[[A1], As]] ->
		     [A1|[A||['COMMA',A] <- As]]
		 end,
    {'Accept', Accept}.

accept-range   =  media-range *(SEMI accept-param) : [_YY1|[A||['SEMI',A]<- _YY2]].

media-range    =  ( "*/*"
                  / ( m-type SLASH "*" )
                  / ( m-type SLASH m-subtype )
                  ) *( SEMI m-parameter ) : 
    case _YY1 of
%%        "*/*" -> "*/*";
	[Type, 'SLASH', SubType] -> {'media-range',Type, SubType}
    end.

accept-param   =  ("q" EQUAL qvalue) / generic-param

qvalue         =  ( "0" [ "." 0*3DIGIT ] )
                  / ( "1" [ "." 0*3("0") ] )

generic-param  =  token [ EQUAL gen-value ]

gen-value      =  token / host / quoted-string

Accept-Encoding  =  "Accept-Encoding" HCOLON
                     [ encoding *(COMMA encoding) ]

encoding         =  codings *(SEMI accept-param)

codings          =  content-coding / "*"

content-coding   =  token

Accept-Language  =  "Accept-Language" HCOLON
                     [ language *(COMMA language) ]

language         =  language-range *(SEMI accept-param)

language-range   =  ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" )

Alert-Info   =  "Alert-Info" HCOLON alert-param *(COMMA alert-param)

alert-param  =  LAQUOT absoluteURI RAQUOT *( SEMI generic-param )

Allow  =  "Allow" HCOLON [Method *(COMMA Method)] : 
        Allowed = case _YY3 of
                      [] -> [];
	              [[M1,Ms]] -> [M1|[M||['COMMA',M]<-Ms]]
                      end,
        {'Allow', Allowed}.

Authorization     =  "Authorization" HCOLON credentials

credentials       =  ("Digest" LWS digest-response)
                     / other-response

digest-response   =  dig-resp *(COMMA dig-resp)

dig-resp          =  username / realm / nonce / digest-uri
                      / dresponse / algorithm / cnonce
                      / opaque / message-qop
                      / nonce-count / auth-param

username          =  "username" EQUAL username-value

username-value    =  quoted-string

digest-uri        =  "uri" EQUAL LDQUOT digest-uri-value RDQUOT

digest-uri-value  =  rquest-uri ; Equal to request-uri as specified
;                     by HTTP/1.1

message-qop       =  "qop" EQUAL qop-value

cnonce            =  "cnonce" EQUAL cnonce-value

cnonce-value      =  nonce-value

nonce-count       =  "nc" EQUAL nc-value

nc-value          =  8LHEX

dresponse         =  "response" EQUAL request-digest

request-digest    =  LDQUOT 32LHEX RDQUOT

auth-param        =  auth-param-name EQUAL
                     ( token / quoted-string )

auth-param-name   =  token

other-response    =  auth-scheme LWS auth-param
                     *(COMMA auth-param)

auth-scheme       =  token

Authentication-Info  =  "Authentication-Info" HCOLON ainfo
                        *(COMMA ainfo)

ainfo                =  nextnonce / message-qop
                         / response-auth / cnonce
                         / nonce-count

nextnonce            =  "nextnonce" EQUAL nonce-value

response-auth        =  "rspauth" EQUAL response-digest

response-digest      =  LDQUOT *LHEX RDQUOT

Call-ID  =  ( "Call-ID" / "i" ) HCOLON callid : {'Call-ID', _YY3}.

callid   =  word [ "@" word ] : lists:flatten(_YY).

Call-Info   =  "Call-Info" HCOLON info *(COMMA info)

info        =  LAQUOT absoluteURI RAQUOT *( SEMI info-param)

info-param  =  ( "purpose" EQUAL ( "icon" / "info"
               / "card" / token ) ) / generic-param

Contact        =  ("Contact" / "m" ) HCOLON
                  ( STAR / (contact-param *(COMMA contact-param))) :
    {'Contact', _YY3}.

contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)

name-addr      =  [ display-name ] LAQUOT addr-spec RAQUOT : {'name-addr', _YY1, _YY3}.

addr-spec      =  SIP-URI / SIPS-URI / absoluteURI

display-name   =  quoted-string / *(token LWS)

contact-params     =  c-p-q / c-p-expires
                      / contact-extension

c-p-q              =  "q" EQUAL qvalue : {'c-p-q', _YY3}.

c-p-expires        =  "expires" EQUAL delta-seconds : {'c-p-expires', _YY3}.

contact-extension  =  generic-param : {'contact-extension', _YY}.

delta-seconds      =  1*DIGIT : list_to_integer(_YY).

Content-Disposition   =  "Content-Disposition" HCOLON
                         disp-type *( SEMI disp-param )

disp-type             =  "render" / "session" / "icon" / "alert"
                         / disp-extension-token

disp-param            =  handling-param / generic-param

handling-param        =  "handling" EQUAL
                         ( "optional" / "required"
                         / other-handling )

other-handling        =  token

disp-extension-token  =  token

Content-Encoding  =  ( "Content-Encoding" / "e" ) HCOLON
                     content-coding *(COMMA content-coding)

Content-Language  =  "Content-Language" HCOLON
                     language-tag *(COMMA language-tag)

language-tag      =  primary-tag *( "-" subtag )

primary-tag       =  1*8ALPHA

subtag            =  1*8ALPHA

Content-Length  =  ( "Content-Length" / "l" ) HCOLON 1*DIGIT : {'Content-Length', list_to_integer(_YY3)}.

Content-Type     =  ( "Content-Type" / "c" ) HCOLON media-type : {'Content-Type', _YY3}.

media-type       =  m-type SLASH m-subtype *(SEMI m-parameter) :
    {'media-type', _YY1, _YY3, [P||['SEMI',P]<-_YY4]}.

m-type           =  discrete-type / composite-type

discrete-type    =  "text" / "image" / "audio" / "video"
                    / "application" / extension-token

composite-type   =  "message" / "multipart" / extension-token

extension-token  =  ietf-token / x-token

ietf-token       =  token

x-token          =  "x-" token

m-subtype        =  extension-token / iana-token

iana-token       =  token

m-parameter      =  m-attribute EQUAL m-value : {'m-parameter', _YY1, _YY3}.

m-attribute      =  token

m-value          =  token / quoted-string

CSeq  =  "CSeq" HCOLON 1*DIGIT LWS Method : {'CSeq', list_to_integer(_YY3), _YY5}.

Date          =  "Date" HCOLON SIP-date

SIP-date      =  rfc1123-date

rfc1123-date  =  wkday "," SP date1 SP timex SP "GMT"

date1         =  2DIGIT SP month SP 4DIGIT
                 ; day month year (e.g., 02 Jun 1982)

timex         =  2DIGIT ":" 2DIGIT ":" 2DIGIT
                 ; 00:00:00 - 23:59:59

wkday         =  "Mon" / "Tue" / "Wed"
                 / "Thu" / "Fri" / "Sat" / "Sun"

month         =  "Jan" / "Feb" / "Mar" / "Apr"
                 / "May" / "Jun" / "Jul" / "Aug"
                 / "Sep" / "Oct" / "Nov" / "Dec"

Error-Info  =  "Error-Info" HCOLON error-uri *(COMMA error-uri)

error-uri   =  LAQUOT absoluteURI RAQUOT *( SEMI generic-param )

Expires     =  "Expires" HCOLON delta-seconds

From        =  ( "From" / "f" ) HCOLON from-spec : {'From', _YY3}.

from-spec   =  ( name-addr / addr-spec )
               *( SEMI from-param ) :  {'from-spec', _YY1, [P||['SEMI',P] <-_YY2]}.

from-param  =  tag-param / generic-param

tag-param   =  "tag" EQUAL token : {tag, _YY3}.

In-Reply-To  =  "In-Reply-To" HCOLON callid *(COMMA callid)

Max-Forwards  =  "Max-Forwards" HCOLON 1*DIGIT : {'Max-Forwards', list_to_integer(_YY3)}.

MIME-Version  =  "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT

Min-Expires  =  "Min-Expires" HCOLON delta-seconds : {'Min-Expires', _YY3}.

Organization  =  "Organization" HCOLON [TEXT-UTF8-TRIM]

Priority        =  "Priority" HCOLON priority-value

priority-value  =  "emergency" / "urgent" / "normal"
                   / "non-urgent" / other-priority

other-priority  =  token

Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge

challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))
                       / other-challenge

other-challenge     =  auth-scheme LWS auth-param
                       *(COMMA auth-param)

digest-cln          =  realm / domain / nonce
                        / opaque / stale / algorithm
                        / qop-options / auth-param

realm               =  "realm" EQUAL realm-value

realm-value         =  quoted-string

domain              =  "domain" EQUAL LDQUOT URI
                       *( 1*SP URI ) RDQUOT

URI                 =  absoluteURI / abs-path

nonce               =  "nonce" EQUAL nonce-value

nonce-value         =  quoted-string

opaque              =  "opaque" EQUAL quoted-string

stale               =  "stale" EQUAL ( "true" / "false" )

algorithm           =  "algorithm" EQUAL ( "MD5" / "MD5-sess"
                       / token )

qop-options         =  "qop" EQUAL LDQUOT qop-value
                       *("," qop-value) RDQUOT

qop-value           =  "auth" / "auth-int" / token

Proxy-Authorization  =  "Proxy-Authorization" HCOLON credentials

Proxy-Require  =  "Proxy-Require" HCOLON option-tag
                  *(COMMA option-tag)
option-tag     =  token

Record-Route  =  "Record-Route" HCOLON rec-route *(COMMA rec-route) :
    {'Record-Route', [_YY3|[RR||['COMMA',RR]<- _YY4]]}.

rec-route     =  name-addr *( SEMI rr-param )

rr-param      =  generic-param

Reply-To      =  "Reply-To" HCOLON rplyto-spec

rplyto-spec   =  ( name-addr / addr-spec )
                 *( SEMI rplyto-param )

rplyto-param  =  generic-param

Require       =  "Require" HCOLON option-tag *(COMMA option-tag)

Retry-After  =  "Retry-After" HCOLON delta-seconds
                [ comment ] *( SEMI retry-param )

retry-param  =  ("duration" EQUAL delta-seconds)
                / generic-param

Route        =  "Route" HCOLON route-param *(COMMA route-param) : {'Route', [_YY3|[P||['COMMA',P]<- _YY4]]}.

route-param  =  name-addr *( SEMI rr-param ) : 
    {'route-param', _YY1, [P||['SEMI',P]<-_YY2]}.

Server           =  "Server" HCOLON server-val *(LWS server-val)

server-val       =  product / comment

product          =  token [SLASH product-version]

product-version  =  token

Subject  =  ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]

Supported  =  ( "Supported" / "k" ) HCOLON
              [option-tag *(COMMA option-tag)]

Timestamp  =  "Timestamp" HCOLON 1*(DIGIT)
               [ "." *(DIGIT) ] [ LWS delay ]

delay      =  *(DIGIT) [ "." *(DIGIT) ]

To        =  ( "To" / "t" ) HCOLON ( name-addr
             / addr-spec ) *( SEMI to-param ) : {'To', _YY3, [P||[_,P]<- _YY4]}.

to-param  =  tag-param / generic-param

Unsupported  =  "Unsupported" HCOLON option-tag *(COMMA option-tag)

User-Agent  =  "User-Agent" HCOLON server-val *(LWS server-val)

Via               =  ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm) :
    {'Via', [_YY3| [VP||['COMMA',VP]<-_YY4]]}.

via-parm          =  sent-protocol LWS sent-by *( SEMI via-params ) :
   {'via-parm', _YY1, _YY3, [P||['SEMI',P]<-_YY4]}.

via-params        =  via-ttl / via-maddr
                     / via-received / via-branch
                     / via-extension

via-ttl           =  "ttl" EQUAL ttl : {'via-ttl', _YY3}.

via-maddr         =  "maddr" EQUAL host : {'via-maddr', _YY3}.

via-received      =  "received" EQUAL (IPv4address / IPv6address) : {'via-received', _YY3}.

via-branch        =  "branch" EQUAL token : {'via-branch', _YY3}.

via-extension     =  generic-param

sent-protocol     =  protocol-name SLASH protocol-version
                     SLASH transport : {'sent-protocol', _YY1, _YY3, _YY5}.

protocol-name     =  "SIP" / token

protocol-version  =  token

transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
                     / other-transport

sent-by           =  host [ COLON port ] : {'sent-by', _YY1, case _YY2 of [] -> []; [[_, Port]] -> Port end}.

ttl               =  1*3DIGIT ; 0 to 255

Warning        =  "Warning" HCOLON warning-value *(COMMA warning-value)

warning-value  =  warn-code SP warn-agent SP warn-text

warn-code      =  3DIGIT

warn-agent     =  hostport / pseudonym
                  ;  the name or pseudonym of the server adding
                  ;  the Warning header, for use in debugging

warn-text      =  quoted-string

pseudonym      =  token

WWW-Authenticate  =  "WWW-Authenticate" HCOLON challenge

extension-header  =  header-name HCOLON header-value : {'extension-header', _YY1, _YY3}.

header-name       =  token

header-value      =  *(TEXT-UTF8char / UTF8-CONT / LWS)

message-body  =  *OCTET

