#include "gen_classes.h" #include "Regex.h" namespace t3devlib { namespace gen { // // Implementation of the decoder for SDP // // SIP quoted strings messages allow multiple ways of representing // some characters (raw unicode or escaped). This function is used // to normalise the content so that two equivalent representation // will result in the same TTCN-3 charstring. // void normalise_quoted_string (Charstring& cs, bool remove_quotes = false) throw (DecodeError) { std::string result; //FIXME: how LWS shall be normalised ? const unsigned char* p = cs.GetValueBin(); const unsigned char* end = p + (cs.GetLength() / 8); if (remove_quotes) { if ((end - p) < 2) goto error_malformed; if ((*p++ != '"') | (*--end != '"')) goto error_malformed; } for ( ; p!=end ; p++) { switch (*p) { case '\r': //LWS case '\n': case ' ': //WSP case '\v': case '\t': case '\f': case 0x21: //! // plain text result += *p; break; case '\\': // escaped character p++; if ((p == end) || ((*p == '\r') | (*p == '\n'))) { // cannot be escaped // (should never happen since we checked it wit a regex before) DecodeError e (&cs); e.Msg() << "Invalid escaped sequence in quoted string: \\\\x" << std::hex << ((int) *p) << std::endl; throw e; } // valid escaped character result += *p; break; default: if ((*p >= 0x23) && (*p <= 0x7e)) { // plain text result += *p; } else if (*p > 127) { // UTF-8 character // // FIXME: how to represent UTF-8 chars ? ('%xx' escape sequences are not used here) result += *p; } else { // non allowed character // (should never happen since we checked it wit a regex before) DecodeError e (&cs); e.Msg() << "Invalid character in quoted string: \\x" << std::hex << ((int) *p) << std::endl; throw e; } } } // replace the string with the quoted string { Bytestring& bs = cs; bs.SetValue (result); } return; error_malformed: DecodeError e(&cs); e.Msg() << "Malformed quoted string: " << cs.GetValue() << endl; throw e; } static inline bool asciichar_is_displayable (char c) { if ((c >= 32) && (c<127)) return true; return (c == '\r') | (c == '\n') | (c == '\t') | (c == '%'); } // SIP tokens allow multiple ways of representing some characters (raw // unicode or escaped). This function is used to normalise the content so // that two equivalent representation will result in the same TTCN-3 // charstring. // void normalise_escaped_string (Charstring& cs) throw (DecodeError) { std::string result; const unsigned char* p = cs.GetValueBin(); const unsigned char* end = p + (cs.GetLength() / 8); for ( ; p!=end ; p++) { unsigned char c; if (*p == '%') { // escaped char %xx if ((end - p) < 3) goto error_malformed; char buff[3] = { p[1], p[2], '\0'}; p += 2; char* next; c = strtol(buff, &next, 16); if (next != &buff[2]) goto error_malformed; //TODO: check that the result is UTF-8 valid ? } else { c = *p; } if (asciichar_is_displayable(c)) { // 7-bit character result += c; } else { // 8-bit character and control characters // -> escape it char buff[4]; sprintf (buff, "%%%02x", c); result += buff; } } // replace the string with the quoted string { Bytestring& bs = cs; bs.SetValue (result); } return; error_malformed: DecodeError e(&cs); e.Msg() << "Malformed string: " << cs.GetValue() << endl; throw e; } //WSP: space, htab, vtab, form feed #define SIPCHARS_WSP " \t\v\f" #define SIPREG_LWS "(?:[" SIPCHARS_WSP "]*\\r\\n)?[" SIPCHARS_WSP "]+" #define SIPREG_SWS "(?:" SIPREG_LWS ")?" // move past the possible leading linear whitespaces in the buffer void remove_whitespace (Buffer & buffer) { static Regex reg_ws ("^" SIPREG_LWS); if (reg_ws.Match (buffer)) { int nPos = buffer.GetPosition() + reg_ws.GetMatchedLength(); buffer.SetPosition (nPos); } } void read_sp (Buffer & buffer, Variable* v) { static Regex reg_ws ("^[ \t]+"); reg_ws.AssertMatch (buffer, v); int nPos = buffer.GetPosition() + reg_ws.GetMatchedLength(); buffer.SetPosition (nPos); } bool is_sip_scheme (const char * pszScheme) { return strncasecmp(pszScheme, "sip", 3) == 0 || strncasecmp(pszScheme, "sips", 4) == 0; } bool is_tel_scheme (const char * pszScheme) { return strncasecmp(pszScheme, "tel", 3) == 0 || strncasecmp(pszScheme, "fax", 3) == 0 || strncasecmp(pszScheme, "modem", 5) == 0; } // Definition of character classes used to be used in the regular expressions // (within []) #define SIPCHARS_MARK "\\-_.!~*'()" #define SIPCHARS_ALFA "A-Za-z" #define SIPCHARS_ALFANUM "0-9" SIPCHARS_ALFA #define SIPCHARS_HEXA "0-9A-Fa-f" #define SIPCHARS_UNRESERVED SIPCHARS_ALFANUM SIPCHARS_MARK #define SIPCHARS_RESERVED ";/?:@&=+$," #define SIPCHARS_USER_UNRESERVED "&=+$,;?/" #define SIPCHARS_UTF8_NONASCII "\x80-\xFD" #define SIPCHARS_TEXT_UTF8CHAR "\x21-\xFD" // Definition of common regular expression reused many times within the // decoder // // Note: these definitions shall not contain any group match '(' ')' to avoid // side effect (the index of the subsequent group match would be shifted) // -> all parenthesis group needed should be implemented with '(?:' ')' so // that they are not indexed // #define SIPREG_ESCAPED "(%[0-9A-Fa-f]{2})" #define SIPREG_TOKEN "[" SIPCHARS_ALFANUM ".!%*_+`'~\\-]+" #define SIPREG_TOKEN_NODOT "[" SIPCHARS_ALFANUM "!%*_+`'~\\-]+" #define SIPREG_WORD "(?:[][" SIPCHARS_ALFANUM "\\-.!%*_+`'~()<>:\\\\\"/?{}])+" #define SIPREG_ASCII_WITHOUT_COMMA "[\\x21-\\x2B\\x2D-\\x7E]+" #define SIPREG_TEXT_UTF8_TRIM "[\x21-\xFD]([\x21-\xFD]|(" SIPREG_LWS "))*" // sip version #define SIPREG_SIP_VERSION "SIP/[0-9]\\.[0-9]" // header name #define SIPREG_HNAME "(?:[][/?:+$" SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")+" // host name #define SIPREG_TOPLABEL "[" SIPCHARS_ALFA "]([" SIPCHARS_ALFANUM "\\-]*[" SIPCHARS_ALFANUM "])?" #define SIPREG_DOMAINLABEL "[" SIPCHARS_ALFANUM "]([" SIPCHARS_ALFANUM "\\-]*[" SIPCHARS_ALFANUM "])?" #define SIPREG_HOSTNAME "(" SIPREG_DOMAINLABEL "\\.)*" SIPREG_TOPLABEL "\\.?" #define SIPREG_HCOLON "[ ]*:" SIPREG_SWS #define SIPREG_COMMA SIPREG_SWS "[,]" SIPREG_SWS #define SIPREG_SEMI SIPREG_SWS "[;]" SIPREG_SWS #define SIPREG_EQUAL SIPREG_SWS "[=]" SIPREG_SWS #define SIPREG_SLASH SIPREG_SWS "[/]" SIPREG_SWS // without leading and trailing whitespace #define SIPREG_QUOTED_PAIR "[\\x5C][\\x00-\\x09\\x0B\\x0C\\x0E-\\x7F]" #define SIPREG_QUOTED_STRING "[\"]((" SIPREG_LWS ")|[]!#-[^-~" SIPCHARS_UTF8_NONASCII"]|(" SIPREG_QUOTED_PAIR "))*[\"]" #define SIPREG_DISPLAY_NAME "((" SIPREG_TOKEN "(" SIPREG_LWS SIPREG_TOKEN ")*)|(" SIPREG_QUOTED_STRING "))" #define SIPREG_COMMENT "[(]((" SIPREG_LWS ")|[\\x21-\\x5B]|[\\x5D-\\xFD]|(" SIPREG_QUOTED_PAIR "))*[)]" // IPv4 #define SIPREG_IP4 "([0-9]{1,3}\\.){3}[0-9]{1,3}" // IPv6 #define SIPREG_HEX4 "[" SIPCHARS_HEXA "]{1,4}" #define SIPREG_HEXSEQ SIPREG_HEX4 "([:]" SIPREG_HEX4 ")*" #define SIPREG_HEXPART "(((" SIPREG_HEXSEQ ")?[:]{2}(" SIPREG_HEXSEQ ")?)|(" SIPREG_HEXSEQ "))" #define SIPREG_IP6 "[[]" SIPREG_HEXPART "([:]" SIPREG_IP4 ")?[]]" // host #define SIPREG_HOST "((" SIPREG_HOSTNAME ")|(" SIPREG_IP4 ")|(" SIPREG_IP6 "))" #define SIPREG_ABSOLUTE_URI "([" SIPCHARS_UNRESERVED "/;?:@&=+$,]|" SIPREG_ESCAPED ")+" // phone number (global or local) #define SIPREG_PHONE_NUMBER "(([+][\\-0-9.()]+)|[\\-0-9()*#A-Da-dPpWw]+)" #define SIPCHARS_PPARAM_UNRESERVED "][/:&+$" #define SIPREG_PPARAM "([" SIPCHARS_PPARAM_UNRESERVED SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")" #define SIPREG_PPARAM_ALLOWED "[" SIPCHARS_PPARAM_UNRESERVED SIPCHARS_UNRESERVED ";=%]+" #define SIPCHARS_HPARAM_UNRESERVED "][/?:+$" #define SIPREG_HPARAM "([" SIPCHARS_HPARAM_UNRESERVED SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")" #define SIPREG_HPARAM_ALLOWED "[" SIPCHARS_HPARAM_UNRESERVED SIPCHARS_UNRESERVED ";=%]+" #define SIPREG_TELPARAM_NAME "[!#$%&'*+\\-.0-9A-Z^_`a-z|~]+" #define SIPREG_TELPARAM_VALUE "([\\x21\\x23-\\x3A\\x3C-\\x7E]+|(" SIPREG_QUOTED_STRING "))" #define SIPREG_TELPARAMS "([;]" SIPREG_TELPARAM_NAME "([=]" SIPREG_TELPARAM_VALUE ")?)+" #define SIPREG_GPARAM_VALUE "(([" SIPCHARS_ALFANUM ".!%*_+`'~\\-:]+)|(" SIPREG_QUOTED_STRING "))" // content type parameter #define SIPREG_M_PARAMETER SIPREG_TOKEN SIPREG_EQUAL "(?:" SIPREG_TOKEN "|" SIPREG_QUOTED_STRING ")" bool detect_separator(Regex & reg_separator, Buffer & buffer) { bool bRes; if (bRes = reg_separator.Match(buffer)) reg_separator.MovePast(buffer); return bRes; } bool detect_comma(Buffer & buffer) { Regex reg_comma ("^" SIPREG_COMMA); return detect_separator(reg_comma, buffer); } bool detect_semi(Buffer & buffer) throw (DecodeError) { Regex reg_semi ("^" SIPREG_SEMI); return detect_separator(reg_semi, buffer); } void SipUrl::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_urlParameters && IsPresent(id_urlParameters)) { csSemi.Encode(buffer); } } void SipUrl::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csColon; csColon.SetValue(":"); switch(field_id) { case id_scheme: csColon.Encode(buffer); break; default: break; } } void SipUrl::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_scheme ("^[" SIPCHARS_ALFA "][" SIPCHARS_ALFANUM "+.\\-]*"); static Regex reg_colon ("^[:]"); static Regex reg_userinfo ("^(?:[" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED "]|" SIPREG_ESCAPED ")+(?::(?:[" SIPCHARS_UNRESERVED "&=+$,]|"SIPREG_ESCAPED")*)?[@]"); static Regex reg_phone ("^" SIPREG_PHONE_NUMBER); static Regex reg_hostport ("^[][" SIPCHARS_ALFANUM ":.\\-]+"); static Regex reg_absolute_uri ("^" SIPREG_ABSOLUTE_URI); static Regex reg_urlParams ("^;" SIPREG_PPARAM_ALLOWED); static Regex reg_headers ("^[?]" SIPREG_PPARAM_ALLOWED); static Regex reg_telParams ("^" SIPREG_TELPARAMS); const char * pszScheme; switch (id) { case id_scheme: reg_scheme.AssertMatch (buffer, this); SetHypFieldLength (id, reg_scheme.GetMatchedLength()); break; case id_userInfo: reg_colon.AssertMatch(buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); pszScheme = Get_scheme().GetValue(); SetHypFieldIsPresent (id, 0); // user-info is not decoded in case of absoluteURI if (is_sip_scheme(pszScheme)) { if (reg_userinfo.Match (buffer)) { SetHypFieldIsPresent (id, 1); SetHypFieldLength (id, reg_userinfo.GetMatchedLength() - 8); } } // telephone numbers are decoded to the userInfo field else if (is_tel_scheme(pszScheme)){ reg_phone.AssertMatch(buffer, this); SetHypFieldIsPresent (id, 1); SetHypFieldLength (id, reg_phone.GetMatchedLength()); } else { // absoluteURI if (reg_absolute_uri.Match (buffer)) { SetHypFieldIsPresent (id, 1); SetHypFieldLength(id, reg_absolute_uri.GetMatchedLength()); } } break; case id_hostPort: pszScheme = Get_scheme().GetValue(); if (is_sip_scheme(pszScheme)) { // remove '@' if (IsPresent (id_userInfo)) { buffer.SetPosition(buffer.GetPosition() + 8); } if (reg_hostport.Match (buffer)) { SetHypFieldIsPresent (id, 1); SetHypFieldLength(id, reg_hostport.GetMatchedLength()); } else if (IsPresent (id_userInfo)) { reg_hostport.Error(this, buffer); } else { SetHypFieldIsPresent (id, 0); } } else { // tel or absoluteURI SetHypFieldIsPresent(id, 0); } break; case id_urlParameters: pszScheme = Get_scheme().GetValue(); if (is_sip_scheme(pszScheme) && reg_urlParams.Match (buffer)){ SetHypFieldIsPresent (id, 1); SetHypFieldLength(id, reg_urlParams.GetMatchedLength()); } else if (is_tel_scheme(pszScheme)) { // "tel" parameters have a different syntax (e.g. & is allowed within both id and values) if (reg_telParams.Match (buffer)) { SetHypFieldIsPresent (id, 1); SetHypFieldLength(id, reg_telParams.GetMatchedLength()); } else { SetHypFieldIsPresent(id, 0); } } else { SetHypFieldIsPresent(id, 0); } break; case id_headers: pszScheme = Get_scheme().GetValue(); if (is_sip_scheme(pszScheme) && reg_headers.Match (buffer)){ SetHypFieldIsPresent (id, 1); SetHypFieldLength(id, reg_headers.GetMatchedLength()); } else { SetHypFieldIsPresent(id, 0); } break; } } void UserInfo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csColon; csColon.SetValue(":"); switch(field_id) { case id_password: csColon.Encode(buffer); break; default: break; } } void UserInfo::PostEncode (Buffer& buffer) throw (EncodeError) { Charstring csAt; csAt.SetValue("@"); csAt.Encode(buffer); } void UserInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_username ("^([" SIPCHARS_UNRESERVED SIPCHARS_USER_UNRESERVED "]|" SIPREG_ESCAPED ")+"); static Regex reg_colon ("^[:]"); static Regex reg_password ("^([&=+$," SIPCHARS_UNRESERVED "]|" SIPREG_ESCAPED ")*"); static Regex reg_absolute_uri ("^" SIPREG_ABSOLUTE_URI); // absoluteURI is mapped into SipUrl.userInfo.userOrTelephoneSubscriber and requires special handling Variable* parent = GetParent(); bool bRequestUri = false; if (parent != NULL) { const char * pszParName = parent->GetTypeName(); if (strcmp(pszParName, "SipUrl") == 0) { SipUrl * pSipUrl = dynamic_cast(parent); const char * pszScheme = pSipUrl->Get_scheme().GetValue(); bRequestUri = !is_sip_scheme(pszScheme); } } Regex * pRegex; switch (id) { case id_userOrTelephoneSubscriber: pRegex = bRequestUri ? ®_absolute_uri : ®_username; pRegex->AssertMatch (buffer, this); SetHypFieldLength(id, pRegex->GetMatchedLength()); break; case id_password: if(!bRequestUri && reg_colon.Match(buffer)) { buffer.SetPosition(buffer.GetPosition() + 8); SetHypFieldIsPresent (id, 1); reg_password.AssertMatch (buffer, this); } else { SetHypFieldIsPresent (id, 0); } break; } } void UserInfo::PostDecode (Buffer& buffer) throw (DecodeError) { if (IsPresent (id_userOrTelephoneSubscriber)) normalise_escaped_string (Get_userOrTelephoneSubscriber()); if (IsPresent (id_password)) normalise_escaped_string (Get_password()); } void HostPort::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csColon; csColon.SetValue(":"); switch(field_id) { case id_portField: if(IsPresent(field_id)) { Get_portField().SetFormat(Integer::AsciiDecimal); csColon.Encode(buffer); } break; default: break; } } void HostPort::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_host ("^" SIPREG_HOST); static Regex reg_colon ("^:"); switch (id) { case id_host: // host is always present SetHypFieldIsPresent(id, 1); reg_host.AssertMatch (buffer, this); SetHypFieldLength(id, reg_host.GetMatchedLength()); break; case id_portField: if(reg_colon.Match (buffer)) { buffer.SetPosition(buffer.GetPosition() + 8); SetHypFieldIsPresent (id, 1); Get_portField().SetFormat(Integer::AsciiDecimal); } else { SetHypFieldIsPresent (id, 0); } break; } } void SemicolonParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id != 0) { csSemi.Encode(buffer); } } void SemicolonParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_SEMI); if (reg_separator.Match(buffer)) // the separator can be in the beginning reg_separator.MovePast(buffer); } void SemicolonParam_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_semi (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void AmpersandParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csAmpersand, csQuestion; csAmpersand.SetValue("&"); csQuestion.SetValue("?"); if(field_id == 0) { csQuestion.Encode(buffer); } else { csAmpersand.Encode(buffer); } } void AmpersandParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_start ("^[?]"); static Regex reg_separator ("^[&]"); if (!buffer.GetBitsLeft()) return; if (GetSize() == 0){ reg_start.AssertMatch(buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); } else if (reg_separator.Match(buffer)) buffer.SetPosition(buffer.GetPosition() + 8); else SetHypSize(-2); } void CommaParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void CommaParam_List::PreDecode (Buffer& buffer) throw (DecodeError) { Variable* parent = GetParent(); if (parent != NULL) { const char * pszParName = parent->GetTypeName(); if (strcmp(pszParName, "Credentials") == 0 || strcmp(pszParName, "AuthenticationInfo") == 0){ SetHypSize (GetSize() + 1); SetHypAppend (1); } } } void CommaParam_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); if (GetSize() > 0 && !reg_content.Match(buffer)) { SetHypSize(-2); } } void CommaParam_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); if (detect_comma (buffer) && reg_content.Match (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void GenericParam::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csEqual; csEqual.SetValue("="); switch(field_id) { case id_paramValue: if(IsPresent(field_id)) { csEqual.Encode(buffer); } break; default: break; } } void GenericParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_equal ("^" SIPREG_EQUAL); static Regex reg_pparname ("^" SIPREG_PPARAM "+"); static Regex reg_pparvalue ("^" SIPREG_PPARAM "*"); static Regex reg_hparname ("^" SIPREG_HPARAM "+"); static Regex reg_hparvalue ("^" SIPREG_HPARAM "*"); static Regex reg_telparname ("^" SIPREG_TELPARAM_NAME); static Regex reg_telparvalue ("^" SIPREG_TELPARAM_VALUE); static Regex reg_gparname ("^" SIPREG_TOKEN); static Regex reg_gparvalue ("^" SIPREG_GPARAM_VALUE); Regex * preg_name = NULL; Regex * preg_value; bool bMandatoryParam = false; Variable* parent = GetParent(); if (parent == NULL) throw DecodeError (this, "Parent type cannot be null\n"); const char * pszParName = parent->GetTypeName(); if (strcmp(pszParName, "SemicolonParam_List") == 0){ parent = parent->GetParent(); if (parent != NULL && strcmp (parent->GetTypeName(), "SipUrl") == 0) { SipUrl * pSipUrl = dynamic_cast(parent); const char * pszScheme = pSipUrl->Get_scheme().GetValue(); if (is_sip_scheme(pszScheme)) { preg_name = ®_pparname; preg_value = ®_pparvalue; } else if (is_tel_scheme(pszScheme)) { preg_name = ®_telparname; preg_value = ®_telparvalue; } } if (preg_name == NULL) { preg_name = ®_gparname; preg_value = ®_gparvalue; } } else if (strcmp(pszParName, "AmpersandParam_List") == 0){ preg_name = ®_hparname; preg_value = ®_hparvalue; bMandatoryParam = true; } else if (strcmp(pszParName, "CommaParam_List") == 0){ preg_name = ®_gparname; preg_value = ®_gparvalue; } else { std::string message ("Unexpected parent type of parameter record: '"); message += pszParName; message += '\n'; throw DecodeError (this, message); } char c; switch (id) { case id_id: preg_name->AssertMatch (buffer, this); SetHypFieldLength (id, preg_name->GetMatchedLength()); break; case id_paramValue: if (bMandatoryParam) reg_equal.AssertMatch(buffer, this); if(bMandatoryParam || (buffer.GetBitsLeft() && reg_equal.Match(buffer))) { buffer.SetPosition(buffer.GetPosition() + reg_equal.GetMatchedLength()); preg_value->AssertMatch (buffer, this); SetHypFieldIsPresent (id, 1); SetHypFieldLength (id, preg_value->GetMatchedLength()); } else { SetHypFieldIsPresent (id, 0); } break; } } void RequestLine::PostEncode (Buffer& buffer) throw (EncodeError) { Charstring cs; cs.SetValue("\r\n"); cs.Encode(buffer); } void RequestLine::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring cs; cs.SetValue(" "); switch(field_id) { case id_method: case id_requestUri: cs.Encode(buffer); break; default: break; } } void GenericParam::PostDecode (Buffer& buffer) throw (DecodeError) { Variable* param_list = GetParent(); if (!param_list) return; Variable* parent = param_list->GetParent(); if (!parent) return; const char* parent_type = parent->GetTypeName(); if (strcmp (parent_type, "SipUrl") == 0) { normalise_escaped_string (Get_id()); } if (IsPresent (id_paramValue)) { Charstring& value = Get_paramValue(); if (value.GetLength() && (*value.GetValueBin() == '"')) { normalise_quoted_string (value, true); } else { const char* par_name = Get_id().GetValue(); //TODO: add other unescaped params if (strcmp (parent_type, "ViaBody") == 0) { if ((strcmp (par_name, "branch") == 0) || (strcmp (par_name, "ttl") == 0) || (strcmp (par_name, "maddr") == 0) || (strcmp (par_name, "received") == 0)) goto skip_escape; } else if (strcmp (parent_type, "From") == 0) { if (strcmp (par_name, "tag") == 0) goto skip_escape; } else if (strcmp (parent_type, "PChargingVector") == 0) { if (strcmp (par_name, "icid-value") == 0) goto skip_escape; } do_escape: normalise_escaped_string (value); skip_escape: ; } } } void RequestLine::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_method ("^" SIPREG_TOKEN); static Regex reg_request_uri ("[^ \t\n\r]+"); static Regex reg_sip_version (SIPREG_SIP_VERSION); switch (id) { case id_method: reg_method.AssertMatch (buffer, this); SetHypFieldLength (id, reg_method.GetMatchedLength()); break; case id_requestUri: read_sp (buffer, this); reg_request_uri.AssertMatch (buffer, this); SetHypFieldLength (id, reg_request_uri.GetMatchedLength()); break; case id_sipVersion: read_sp (buffer, this); reg_sip_version.AssertMatch (buffer, this); SetHypFieldLength (id, reg_sip_version.GetMatchedLength()); break; } } void RequestLine::PostDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_crlf ("^\r\n"); reg_crlf.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + reg_crlf.GetMatchedLength()); } const char* Method::msSipMethods[] = { "ACK_E", "BYE_E", "CANCEL_E", "INVITE_E", "OPTIONS_E", "REGISTER_E", "PRACK_E", "SUBSCRIBE_E", "NOTIFY_E", "PUBLISH_E", "REFER_E", "UPDATE_E", "MESSAGE_E", "INFO_E", "UNKNOWN_METHOD_E" , "" }; const char* Method::msMethodValues[] = { "ACK", "BYE", "CANCEL", "INVITE", "OPTIONS", "REGISTER", "PRACK", "SUBSCRIBE", "NOTIFY", "PUBLISH", "REFER", "UPDATE", "MESSAGE", "INFO" "UNKNOWN_METHOD" , "" }; void Method::Encode (Buffer& buffer) throw (EncodeError) { Charstring c; const char ** ppMethod = msSipMethods; const std::string & val = GetValueString(); int i = 0; while (*(ppMethod[i]) && strcmp(ppMethod[i], val.c_str()) != 0) i++; if (*(ppMethod[i]) == 0) { std::string message ("unsupported enum value '"); message += val; message += '\n'; throw EncodeError (this, message); } c.SetValue(msMethodValues[i]); c.Encode(buffer); } void Method::Decode (Buffer& buffer) throw (DecodeError) { static Regex reg_method ("^" SIPREG_TOKEN); reg_method.AssertMatch (buffer, this); const char ** ppValue = msMethodValues; const std::string & val = reg_method.GetMatchedString(); int i = 0; while (*(ppValue[i]) && strcmp(ppValue[i], val.c_str()) != 0) // case sensitive!!! i++; if (*(ppValue[i]) == 0) { SetValueString ("UNKNOWN_METHOD_E"); } else { SetValueString (msSipMethods[i]); } buffer.SetPosition(buffer.GetPosition() + reg_method.GetMatchedLength()); } void StatusLine::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS; csWS.SetValue(" "); switch(field_id) { case id_statusCode: Get_statusCode().SetFormat(Integer::AsciiDecimal); case id_reasonPhrase: csWS.Encode(buffer); break; default: break; } } void StatusLine::PostEncode (Buffer& buffer) throw (EncodeError) { Charstring csCRLF; csCRLF.SetValue("\r\n"); csCRLF.Encode(buffer); } void StatusLine::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_sip_version (SIPREG_SIP_VERSION); static Regex reg_status_code ("^[0-9]{3}"); static Regex reg_phrase ("([" SIPCHARS_RESERVED SIPCHARS_UNRESERVED SIPCHARS_UTF8_NONASCII " \t]|" SIPREG_ESCAPED ")*"); switch (id) { case id_sipVersion: reg_sip_version.AssertMatch (buffer, this); SetHypFieldLength (id, reg_sip_version.GetMatchedLength()); break; case id_statusCode: read_sp (buffer, this); reg_status_code.AssertMatch (buffer, this); SetHypFieldLength (id, reg_status_code.GetMatchedLength()); Get_statusCode().SetFormat(Integer::AsciiDecimal); break; case id_reasonPhrase: read_sp (buffer, this); reg_phrase.AssertMatch (buffer, this); SetHypFieldLength (id, reg_phrase.GetMatchedLength()); break; } } void StatusLine::PostDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_crlf ("^\r\n"); reg_crlf.AssertMatch(buffer, this); reg_crlf.MovePast(buffer); normalise_escaped_string (Get_reasonPhrase()); } class SipHeaderMap { public: struct Entry { Entry (const char* name, const char* abbrev, int id_msg_hdr, const char* id_fdn) : mName (name), mAbbrev (abbrev), mIdMessageHeader (id_msg_hdr), mIdFieldName (id_fdn) {} const std::string mName; const std::string mAbbrev; const int mIdMessageHeader; const std::string mIdFieldName; }; static const Entry& GetByName (const std::string& key) { const mMapName_t& m = msInstance.mMapName; mMapName_t::const_iterator it = m.find (key); if (it != m.end()) { return *it->second; } else { return *msInstance.mUndef; } } static const Entry& GetByIdFieldName (const std::string& key) { const std::map& m = msInstance.mMapIdFieldName; std::map ::const_iterator it = m.find (key); if (it != m.end()) { return *it->second; } else { return *msInstance.mUndef; } } static const Entry& GetByIdMessageHeader (int key) { const std::map& m = msInstance.mMapIdMessageHeader; std::map ::const_iterator it = m.find (key); if (it != m.end()) { return *it->second; } else { return *msInstance.mUndef; } } private: void AddEntry (const Entry& entry) { mEntries.push_back(entry); Entry& e = *mEntries.rbegin(); //TODO: check unicity mMapName[e.mName] = &e; mMapName[e.mAbbrev] = &e; mMapIdMessageHeader[e.mIdMessageHeader] = &e; mMapIdFieldName[e.mIdFieldName] = &e; } SipHeaderMap() { #define SIP_HEADER_ADD(name, abbr, msghdr, fdname) AddEntry (Entry (#name, #abbr, MessageHeader::id_ ## msghdr, #fdname)); // Name Abbrev MessageHeader FieldName // field id field id SIP_HEADER_ADD (From, f, fromField, FROM_E); SIP_HEADER_ADD (Via, v, via, VIA_E); SIP_HEADER_ADD (Accept, , accept, ACCEPT_E); SIP_HEADER_ADD (Call-ID, i, callId, CALL_ID_E); SIP_HEADER_ADD (CSeq, , cSeq, CSEQ_E); SIP_HEADER_ADD (Content-Length, l, contentLength, CONTENT_LENGTH_E); SIP_HEADER_ADD (Content-Type, c, contentType, CONTENT_TYPE_E); SIP_HEADER_ADD (Contact, m, contact, CONTACT_E); SIP_HEADER_ADD (To, t, toField, TO_E); SIP_HEADER_ADD (Accept-Encoding, , acceptEncoding, ACCEPT_ENCODING_E); SIP_HEADER_ADD (Accept-Language, , acceptLanguage, ACCEPT_LANGUAGE_E); SIP_HEADER_ADD (Max-Forwards, , maxForwards, MAX_FORWARDS_E); SIP_HEADER_ADD (Alert-Info, , alertInfo, ALERT_INFO_E); SIP_HEADER_ADD (Require, , require, REQUIRE_E); SIP_HEADER_ADD (Proxy-Require, , proxyRequire, PROXY_REQUIRE_E); SIP_HEADER_ADD (Record-Route, , recordRoute, RECORD_ROUTE_E); SIP_HEADER_ADD (Allow, , allow, ALLOW_E); SIP_HEADER_ADD (Authentication-Info, , authenticationInfo, AUTHENTICATION_INFO_E); SIP_HEADER_ADD (Authorization, , authorization, AUTHORIZATION_E); SIP_HEADER_ADD (Call-Info, , callInfo, CALL_INFO_E); SIP_HEADER_ADD (Content-Disposition, , contentDisposition, CONTENT_DISPOSITION_E); SIP_HEADER_ADD (Content-Encoding, e, contentEncoding, CONTENT_ENCODING_E); SIP_HEADER_ADD (Content-Language, , contentLanguage, CONTENT_LANGUAGE_E); SIP_HEADER_ADD (Date, , date, DATE_E); SIP_HEADER_ADD (Error-Info, , errorInfo, ERROR_INFO_E); SIP_HEADER_ADD (Expires, , expires, EXPIRES_E); SIP_HEADER_ADD (In-Reply-To, , inReplyTo, IN_REPLY_TO_E); SIP_HEADER_ADD (MIME-Version, , mimeVersion, MIME_VERSION_E); SIP_HEADER_ADD (Min-Expires, , minExpires, MIN_EXPIRES_E); SIP_HEADER_ADD (Organization, , organization, ORGANIZATION_E); SIP_HEADER_ADD (Priority, , priority, PRIORITY_E); SIP_HEADER_ADD (Proxy-Authenticate, , proxyAuthenticate, PROXY_AUTHENTICATE_E); SIP_HEADER_ADD (Proxy-Authorization, , proxyAuthorization, PROXY_AUTHORIZATION_E); SIP_HEADER_ADD (Reply-To, , replyTo, REPLY_TO_E); SIP_HEADER_ADD (Retry-After, , retryAfter, RETRY_AFTER_E); SIP_HEADER_ADD (Route, , route, ROUTE_E); SIP_HEADER_ADD (Server, , server, SERVER_E); SIP_HEADER_ADD (Supported, , supported, SUPPORTED_E); SIP_HEADER_ADD (Subject, s, subject, SUBJECT_E); SIP_HEADER_ADD (Timestamp, , timestamp, TIMESTAMP_E); SIP_HEADER_ADD (Unsupported, , unsupported, UNSUPPORTED_E); SIP_HEADER_ADD (User-Agent, , userAgent, USER_AGENT_E); SIP_HEADER_ADD (Warning, , warning, WARNING_E); SIP_HEADER_ADD (WWW-Authenticate, , wwwAuthenticate, WWW_AUTHENTICATE_E); SIP_HEADER_ADD (RSeq, , rSeq, RSEQ_E); SIP_HEADER_ADD (RAck, , rAck, RACK_E); SIP_HEADER_ADD (Allow-Events, u, allowEvents, ALLOW_EVENTS_E); SIP_HEADER_ADD (Event, o, event, EVENT_E); SIP_HEADER_ADD (Subscription-State, , subscriptionState, SUBSCRIPTION_STATE_E); SIP_HEADER_ADD (P-Media-Authorization, , pMediaAuthorization, P_MEDIA_AUTHORIZATION_E); SIP_HEADER_ADD (Privacy, , privacy, PRIVACY_E); SIP_HEADER_ADD (P-Asserted-Identity, , pAssertedID, P_ASSERTED_ID_E); SIP_HEADER_ADD (P-Preferred-Identity, , pPreferredID, P_PREFERRED_ID_E); SIP_HEADER_ADD (Reason, , reason, REASON_E); SIP_HEADER_ADD (Path, , path, PATH_E); SIP_HEADER_ADD (Security-Client, , securityClient, SECURITY_CLIENT_E); SIP_HEADER_ADD (Security-Server, , securityServer, SECURITY_SERVER_E); SIP_HEADER_ADD (Security-Verify, , securityVerify, SECURITY_VERIFY_E); SIP_HEADER_ADD (P-Associated-URI, , pAssociatedURI, P_ASSOCIATED_URI_E); SIP_HEADER_ADD (P-Called-Party-ID, , pCalledPartyID, P_CALLED_PARTY_E); SIP_HEADER_ADD (P-Visited-Network-ID, , pVisitedNetworkID, P_VISITED_NETWORK_E); SIP_HEADER_ADD (P-Access-Network-Info, , pAccessNetworkInfo, P_ACCESS_NETWORK_INFO_E); SIP_HEADER_ADD (P-Charging-Function-Addresses, , pChargingFunctionAddresses, P_CHARGING_FUNCTION_ADDRESSES_E); SIP_HEADER_ADD (P-Charging-Vector, , pChargingVector, P_CHARGING_VECTOR_E); SIP_HEADER_ADD (Refer-To, r, referTo, REFER_TO_E); SIP_HEADER_ADD (Replaces, , replaces, REPLACES_E); SIP_HEADER_ADD (Service-Route, , serviceRoute, SERVICE_ROUTE_E); SIP_HEADER_ADD (Accept-Contact, a, acceptContact, ACCEPT_CONTACT_E); SIP_HEADER_ADD (Referred-By, b, referredBy, REFERRED_BY_E); SIP_HEADER_ADD (Session-Expires, , sessionExpires, SESSION_EXPIRES_E); SIP_HEADER_ADD (Min-SE, , minSE, MIN_SE_E); SIP_HEADER_ADD (History-Info, , historyInfo, HISTORY_INFO_E); SIP_HEADER_ADD (P-Early-Media, , pEarlyMedia, P_EARLY_MEDIA_E); SIP_HEADER_ADD (UserToUser, , userToUser, USER_TO_USER_E); SIP_HEADER_ADD (P-Asserted-Service, , pAssertedService, P_ASSERTED_SERVICE_E); { mEntries.push_back(Entry("", "", MessageHeader::id_undefinedHeader_List, "")); Entry& e = *mEntries.rbegin(); mMapIdMessageHeader[e.mIdMessageHeader] = &e; mUndef = &e; } } static SipHeaderMap msInstance; std::list mEntries; Entry* mUndef; class StringCaseInsensitiveComparator { public: bool operator() (const std::string& a, const std::string& b) const { return (strcasecmp (a.c_str(), b.c_str()) < 0); } }; typedef std::map mMapName_t; mMapName_t mMapName; std::map mMapIdFieldName; std::map mMapIdMessageHeader; }; SipHeaderMap SipHeaderMap::msInstance; void MessageHeader::PostEncode (Buffer& buffer) throw (EncodeError) { Charstring csCRLF; csCRLF.SetValue("\r\n"); csCRLF.Encode(buffer); } void MessageHeader::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csCRLF; csCRLF.SetValue("\r\n"); if(IsPresent(field_id) && field_id != id_undefinedHeader_List) { csCRLF.Encode(buffer); } } void MessageHeader::PreDecodeField (Buffer& buffer) throw (DecodeError) { static Regex reg_header_name ("^(" SIPREG_TOKEN ")" SIPREG_HCOLON); static Regex reg_crlf ("^\r\n"); if (reg_crlf.Match (buffer)) { reg_crlf.MovePast (buffer); SetHypNextField (-2); // end of the headers } else { reg_header_name.AssertMatch (buffer, this); const SipHeaderMap::Entry& hdr = SipHeaderMap::GetByName(reg_header_name.GetMatchedString (1)); int id = hdr.mIdMessageHeader; std::cerr << "biiiiiip " << reg_header_name.GetMatchedString(1) << std::endl; // check that this field is not duplicated if (IsPresent(id)) { switch (id) { case id_accept: case id_acceptEncoding: case id_acceptLanguage: case id_alertInfo: case id_allow: case id_authorization: case id_contact: case id_contentEncoding: case id_contentLanguage: case id_errorInfo: case id_inReplyTo: case id_proxyAuthorization: case id_proxyRequire: case id_recordRoute: case id_require: case id_route: case id_supported: case id_unsupported: case id_via: case id_warning: case id_allowEvents: case id_pMediaAuthorization: case id_pAssertedID: case id_pPreferredID: case id_reason: case id_path: case id_securityClient: case id_securityServer: case id_securityVerify: case id_pAssociatedURI: case id_pCalledPartyID: case id_pVisitedNetworkID: case id_acceptContact: case id_historyInfo: case id_pEarlyMedia: case id_undefinedHeader_List: // these fields can appear multiple times break; default: DecodeError e (this); e.Msg() << "Duplicated field in the message: " << hdr.mName << std::endl; throw (e); } } SetHypNextField (id); } } void MessageHeader::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_crlf ("^\r\n"); reg_crlf.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + reg_crlf.GetMatchedLength()); } const char* FieldName::msFields[] = { "ACCEPT_E", "ACCEPT_ENCODING_E", "ACCEPT_LANGUAGE_E", "ALERT_INFO_E", "ALLOW_E", "AUTHENTICATION_INFO_E", "AUTHORIZATION_E", "CALL_ID_E", "CALL_INFO_E", "CONTACT_E", "CONTENT_DISPOSITION_E", "CONTENT_ENCODING_E", "CONTENT_LANGUAGE_E", "CONTENT_LENGTH_E", "CONTENT_TYPE_E", "CSEQ_E", "DATE_E", "ERROR_INFO_E", "EXPIRES_E", "FROM_E", "IN_REPLY_TO_E", "MAX_FORWARDS_E", "MIME_VERSION_E", "MIN_EXPIRES_E", "ORGANIZATION_E", "PRIORITY_E", "PROXY_AUTHENTICATE_E", "PROXY_AUTHORIZATION_E", "PROXY_REQUIRE_E", "RECORD_ROUTE_E", "REPLY_TO_E", "REQUIRE_E", "RETRY_AFTER_E", "ROUTE_E", "SERVER_E", "SUBJECT_E", "SUPPORTED_E", "TIMESTAMP_E", "TO_E", "UNSUPPORTED_E", "USER_AGENT_E", "VIA_E", "WARNING_E", "WWW_AUTHENTICATE_E", "RACK_E", "RSEQ_E", "ALLOW_EVENTS_E", "EVENT_E", "SUBSCRIPTION_STATE_E", "P_MEDIA_AUTHORIZATION_E", "PRIVACY_E", "P_ASSERTED_ID_E", "P_PREFERRED_ID_E", "REASON_E", "REFER_TO_E", "REFERRED_BY_E", "HISTORY_INFO_E", "P_MEDIA_AUTH_E", "PATH_E", "SECURITY_CLIENT_E", "SECURITY_SERVER_E", "SECURITY_VERIFY_E", "P_ACCESS_NETWORK_INFO_E", "P_ASSOCIATED_URI_E", "P_CALLED_PARTY_E", "P_CHARGING_FUNCTION_ADDRESSES_E", "P_CHARGING_VECTOR_E", "P_VISITED_NETWORK_E", "SERVICE_ROUTE_E", "ACCEPT_CONTACT_E", "MIN_SE_E", "SESSION_EXPIRES_E", "P_ASSERTED_SERVICE_E", "P_EARLY_MEDIA_E" , "" }; void FieldName::Encode (Buffer& buffer) throw (EncodeError) { Charstring c; c.SetValue ((SipHeaderMap::GetByIdFieldName(GetValueString()).mName + ": ").c_str()); c.Encode(buffer); } void FieldName::Decode (Buffer& buffer) throw (DecodeError) { static Regex reg_header_name ("^([A-Za-z\\-]+)" SIPREG_HCOLON); reg_header_name.AssertMatch (buffer, this); SetValueString (SipHeaderMap::GetByName(reg_header_name.GetMatchedString (1)).mIdFieldName.c_str()); buffer.SetPosition(buffer.GetPosition() + reg_header_name.GetMatchedLength()); } void Addr_Union::PreDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_name_addr ("^" SIPREG_DISPLAY_NAME "?" SIPREG_SWS "<[^\\r\\n]*>"); mPosition = buffer.GetPosition(); SetHypChosenId ( reg_name_addr.Match (buffer) ? id_nameAddr : id_addrSpecUnion ); } void Addr_Union::PostDecode (Buffer& buffer) throw (DecodeError) { if (GetChosenId() == id_addrSpecUnion) { Variable* parent = GetParent(); if (parent && ( (strcmp (parent->GetTypeName(), "From") == 0) || (strcmp (parent->GetTypeName(), "ContactAddress") == 0) || (strcmp (parent->GetTypeName(), "ReplyTo") == 0) || (strcmp (parent->GetTypeName(), "To") == 0) )) { // in the case we decoded an address not enclosed in <> in a // From, Contact, Reply-To or To header, then we must ensure // that it does not contain comma, semicolon or question mark const unsigned char* start = buffer.GetValueBin() + (mPosition/8); const unsigned char* end = buffer.GetValueBin() + (buffer.GetPosition()/8); for (const unsigned char* p=start ; p!=end ; p++) { switch (*p) { case ';': Get_addrSpecUnion().SetField (SipUrl::id_urlParameters, new Undef); case '?': Get_addrSpecUnion().SetField (SipUrl::id_headers, new Undef); buffer.SetPosition ((p-start) * 8 + mPosition); goto finished; case ',': throw DecodeError (this, "Url must not contain unescaped comma, semicolor or question mark if it is not enclosed with <>\n"); default: ; } } finished: ; } } } void ContactBody::PreDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_asterisk ("^[*]"); if (reg_asterisk.Match (buffer)) { if (GetChosenId() == id_contactAddresses) throw DecodeError (this, "cannot process wildcard; contactAddresses option is already selected\n"); SetHypChosenId (id_wildcard); SetHypFieldLength(id_wildcard, 8); } else { if (GetChosenId() == id_wildcard) throw DecodeError (this, "cannot process address list; wildcart option is already selected\n"); SetHypChosenId (id_contactAddresses); } } void ContactAddress_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void ContactAddress_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void ContactAddress_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void ContactAddress::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_contactParams && IsPresent(id_contactParams)) { csSemi.Encode(buffer); } } void ContactAddress::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_semicolon ("^" SIPREG_SEMI); if (id == id_contactParams) { if(reg_semicolon.Match(buffer)) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void From::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_fromParams && IsPresent(id_fromParams)) { csSemi.Encode(buffer); } } void From::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_semicolon ("^;"); if (id == id_fromParams) { if(reg_semicolon.Match(buffer)) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void To::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_toParams && IsPresent(id_toParams)) { csSemi.Encode(buffer); } } void To::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_semicolon ("^;"); if (id == id_toParams) { if(reg_semicolon.Match(buffer)) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void ReplyTo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_replyToParams && IsPresent(id_replyToParams)) { csSemi.Encode(buffer); } } void ReplyTo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_semicolon ("^;"); if (id == id_replyToParams) { if(reg_semicolon.Match(buffer)) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void Accept::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_accept_args ("^[^;,\\r\\n]"); if (id == id_acceptArgs){ if(reg_accept_args.Match(buffer) || Get_acceptArgs().GetSize() > 0) { SetHypFieldIsPresent (id, 1); } else if (Get_acceptArgs().GetSize() == 0){ SetHypFieldIsPresent (id, 0); } } } void AcceptBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_acceptParam && IsPresent(id_acceptParam)) { csSemi.Encode(buffer); } } void AcceptBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_media_range ("^[^" SIPCHARS_WSP ";,\\r\\n]+"); static Regex reg_semicolon ("^" SIPREG_SEMI); switch (id){ case id_mediaRange: reg_media_range.AssertMatch (buffer, this); SetHypFieldLength(id, reg_media_range.GetMatchedLength()); break; case id_acceptParam: if (reg_semicolon.Match (buffer) ) { SetHypFieldIsPresent(id, 1); } else { SetHypFieldIsPresent(id, 0); } } } void AcceptBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void AcceptBody_List::PreDecode (Buffer& buffer) throw (DecodeError) { // we assume that we are decoding one field at onece // multiple fields are handled by successively decoding // the via field several times in MessageHeader SetHypSize (GetSize() + 1); SetHypAppend (1); } void AcceptBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); if (GetSize() > 0 && !reg_content.Match(buffer)) { SetHypSize(-2); } } void AcceptBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); if (detect_comma (buffer) && reg_content.Match (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void AcceptEncoding::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_content_coding ("^[^,\\r\\n]"); if (id == id_contentCoding){ if(reg_content_coding.Match(buffer) || Get_contentCoding().GetSize() > 0) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void ContentCoding_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void ContentCoding_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); if (GetSize() == 0) reg_content.AssertMatch(buffer, this); else if (!reg_content.Match(buffer)) { SetHypSize(-2); return; } SetHypFieldLength(reg_content.GetMatchedLength()); } void ContentCoding_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); if (detect_comma (buffer) && reg_content.Match (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void AcceptLanguage::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_language_body ("^[^;,\\r\\n]"); if (id == id_languageBody){ if(reg_language_body.Match(buffer) || Get_languageBody().GetSize() > 0) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void LanguageBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_acceptParam && IsPresent(id_acceptParam)) { csSemi.Encode(buffer); } } void LanguageBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_language_range ("^[^" SIPCHARS_WSP ";,\\r\\n]+"); static Regex reg_semicolon ("^" SIPREG_SEMI); switch (id){ case id_languageRange: reg_language_range.AssertMatch (buffer, this); SetHypFieldLength(id, reg_language_range.GetMatchedLength()); break; case id_acceptParam: if (reg_semicolon.Match (buffer)) { SetHypFieldIsPresent(id, 1); } else { SetHypFieldIsPresent(id, 0); } } } void LanguageBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void LanguageBody_List::PreDecode (Buffer& buffer) throw (DecodeError) { // we assume that we are decoding one field at onece // multiple fields are handled by successively decoding // the via field several times in MessageHeader SetHypSize (GetSize() + 1); SetHypAppend (1); } void LanguageBody_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_language ("^[^" SIPCHARS_WSP ";,\\r\\n]+"); if (!reg_language.Match(buffer)) { SetHypSize(-2); return; } } void LanguageBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_language ("^[^" SIPCHARS_WSP ";,\\r\\n]+"); if (detect_comma (buffer) && reg_language.Match (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void MaxForwards::PreEncode (Buffer& buffer) throw (EncodeError) { Get_forwards().SetFormat(Integer::AsciiDecimal); } void MaxForwards::PreDecode (Buffer& buffer) throw (DecodeError) { Get_forwards().SetFormat(Integer::AsciiDecimal); } void AlertInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_alert_info ("^[^;,\\r\\n]"); if (id == id_alertInfoBody){ if(reg_alert_info.Match(buffer) || Get_alertInfoBody().GetSize() > 0) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void AlertInfoBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csLeftAngle, csSemi; csLeftAngle.SetValue("<"); csSemi.SetValue(";"); if(field_id == id_url) { csLeftAngle.Encode(buffer); } if(field_id == id_genericParams && IsPresent(id_genericParams)) { csSemi.Encode(buffer); } } void AlertInfoBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csRightAngle; csRightAngle.SetValue(">"); if(field_id == id_url) { csRightAngle.Encode(buffer); } } void AlertInfoBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_url ("^<" SIPREG_ABSOLUTE_URI ">"); static Regex reg_semicolon ("^" SIPREG_SEMI); switch (id){ case id_url: reg_url.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); SetHypFieldLength(id, reg_url.GetMatchedLength() - 16); break; case id_genericParams: if (reg_semicolon.Match (buffer)) { SetHypFieldIsPresent(id, 1); } else { SetHypFieldIsPresent(id, 0); } } } void AlertInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { switch (id){ case id_url: buffer.SetPosition(buffer.GetPosition() + 8); break; } } void AlertInfoBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void AlertInfoBody_List::PreDecode (Buffer& buffer) throw (DecodeError) { // we assume that we are decoding one field at onece // multiple fields are handled by successively decoding // the via field several times in MessageHeader SetHypSize (GetSize() + 1); SetHypAppend (1); } void AlertInfoBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void Allow::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_allow ("^[^,\\r\\n]"); if (id == id_methods){ if(reg_allow.Match(buffer) || Get_methods().GetSize() > 0) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void Method_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void Method_List::PreDecode (Buffer& buffer) throw (DecodeError) { // we assume that we are decoding one field at onece // multiple fields are handled by successively decoding // the via field several times in MessageHeader SetHypSize (GetSize() + 1); SetHypAppend (1); } void Method_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_TOKEN); if (reg_content.Match (buffer)) { SetHypFieldLength(reg_content.GetMatchedLength()); } else { SetHypSize(-2); return; } } void Method_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_TOKEN); if (detect_comma (buffer) && reg_content.Match (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void CredentialsList::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void CredentialsList::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { } // TODO: Add CredentialsList PreEncode /* type record Authorization { FieldName fieldName (AUTHORIZATION_E), CredentialsList body // changed from Credentials to allow multiple Authorization headers }*/ /* type record ProxyAuthorization { FieldName fieldName (PROXY_AUTHORIZATION_E), CredentialsList credentials // changed from Credentials to allow multiple Authorization headers }*/ void Credentials::PreEncode (Buffer& buffer) throw (EncodeError) { Charstring csDigestWS; csDigestWS.SetValue("Digest "); if(GetChosenId() == id_digestResponse) { csDigestWS.Encode(buffer); } } void Credentials::PreDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_digest ("^[Dd][Ii][Gg][Ee][Ss][Tt]" SIPREG_LWS); if (reg_digest.Match (buffer)) { if (GetChosenId() == id_otherResponse) throw DecodeError (this, "cannot process digest credentials; otherResponse option is already selected\n"); buffer.SetPosition(buffer.GetPosition() + reg_digest.GetMatchedLength()); SetHypChosenId (id_digestResponse); } else { if (GetChosenId() == id_digestResponse) throw DecodeError (this, "cannot process custom credentials; digestResponse option is already selected\n"); SetHypChosenId (id_otherResponse); } } void Challenge::PreEncode (Buffer& buffer) throw (EncodeError) { Charstring csDigestWS; csDigestWS.SetValue("Digest "); if(GetChosenId() == id_digestCln) { csDigestWS.Encode(buffer); } } void Challenge::PreDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_digest ("^[Dd][Ii][Gg][Ee][Ss][Tt]" SIPREG_LWS); if (reg_digest.Match (buffer)) { buffer.SetPosition(buffer.GetPosition() + reg_digest.GetMatchedLength()); SetHypChosenId (id_digestCln); } else { SetHypChosenId (id_otherChallenge); } } void OtherAuth::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS; csWS.SetValue(" "); switch(field_id) { case id_authScheme: csWS.Encode(buffer); break; default: break; } } void OtherAuth::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_auth_scheme ("^" SIPREG_TOKEN); static Regex reg_separator ("^" SIPREG_LWS); switch (id){ case id_authScheme: reg_auth_scheme.AssertMatch (buffer, this); SetHypFieldLength (id, reg_auth_scheme.GetMatchedLength()); break; case id_authParams: reg_separator.AssertMatch(buffer, this); buffer.SetPosition(buffer.GetPosition() + reg_separator.GetMatchedLength()); Get_authParams().SetHypSize (GetSize() + 1); Get_authParams().SetHypAppend (1); break; } } void CallInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_call_info ("^[^;,\\r\\n]"); if (id == id_callInfoBody){ if(reg_call_info.Match(buffer)) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void CallInfoBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csLeftAngle, csSemi; csLeftAngle.SetValue("<"); csSemi.SetValue(";"); if(field_id == id_url) { csLeftAngle.Encode(buffer); } if(field_id == id_infoParams && IsPresent(id_infoParams)) { csSemi.Encode(buffer); } } void CallInfoBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csRightAngle; csRightAngle.SetValue(">"); if(field_id == id_url) { csRightAngle.Encode(buffer); } } void CallInfoBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_url ("^<" SIPREG_ABSOLUTE_URI ">"); static Regex reg_semicolon ("^" SIPREG_SEMI); switch (id){ case id_url: reg_url.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); SetHypFieldLength(id, reg_url.GetMatchedLength() - 16); break; case id_infoParams: if (reg_semicolon.Match (buffer)) { SetHypFieldIsPresent(id, 1); } else { SetHypFieldIsPresent(id, 0); } } } void CallInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { switch (id){ case id_url: buffer.SetPosition(buffer.GetPosition() + 8); break; } } void CallInfoBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void CallInfoBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void ContentDisposition::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_dispositionParams && IsPresent(id_dispositionParams)) { csSemi.Encode(buffer); } } void ContentDisposition::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_disposition_type ("^" SIPREG_TOKEN); static Regex reg_semicolon ("^" SIPREG_SEMI); switch (id){ case id_dispositionType: reg_disposition_type.AssertMatch (buffer, this); SetHypFieldLength(id, reg_disposition_type.GetMatchedLength()); break; case id_dispositionParams: if (reg_semicolon.Match (buffer)) { SetHypFieldIsPresent(id, 1); } else { SetHypFieldIsPresent(id, 0); } } } void LanguageTag_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void LanguageTag_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void LanguageTag_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); reg_content.AssertMatch(buffer, this); SetHypFieldLength(reg_content.GetMatchedLength()); } void LanguageTag_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void Date::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_date ("^[^\\r\\n]+"); if (id == id_sipDate){ reg_date.AssertMatch(buffer, this); SetHypFieldLength(id, reg_date.GetMatchedLength()); } } void ErrorInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_error_info ("^[^;,\\r\\n]"); if (id == id_errorInfo){ if(reg_error_info.Match(buffer) || Get_errorInfo().GetSize() > 0) { SetHypFieldIsPresent (id, 1); } else { SetHypFieldIsPresent (id, 0); } } } void ErrorInfoBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csLeftAngle, csSemi; csLeftAngle.SetValue("<"); csSemi.SetValue(";"); if(field_id == id_uri) { csLeftAngle.Encode(buffer); } if(field_id == id_genericParams && IsPresent(id_genericParams)) { csSemi.Encode(buffer); } } void ErrorInfoBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csRightAngle; csRightAngle.SetValue(">"); if(field_id == id_uri) { csRightAngle.Encode(buffer); } } void ErrorInfoBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_uri ("^<" SIPREG_ABSOLUTE_URI ">"); static Regex reg_semicolon ("^" SIPREG_SEMI); switch (id){ case id_uri: reg_uri.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); SetHypFieldLength(id, reg_uri.GetMatchedLength() - 16); break; case id_genericParams: if (reg_semicolon.Match (buffer)) { SetHypFieldIsPresent(id, 1); } else { SetHypFieldIsPresent(id, 0); } } } void ErrorInfoBody::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { switch (id){ case id_uri: buffer.SetPosition(buffer.GetPosition() + 8); break; } } void ErrorInfoBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void ErrorInfoBody_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void ErrorInfoBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void Expires::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_delta_sec ("^[0-9]+"); switch (id) { case id_deltaSec: reg_delta_sec.AssertMatch (buffer, this); SetHypFieldLength (id, reg_delta_sec.GetMatchedLength()); break; } } void CallidString_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void CallidString_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void CallidString_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_ASCII_WITHOUT_COMMA); reg_content.AssertMatch(buffer, this); SetHypFieldLength(reg_content.GetMatchedLength()); } void CallidString_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void MimeVersion::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csDot; csDot.SetValue("."); switch(field_id) { case id_majorNumber: Get_majorNumber().SetFormat(Integer::AsciiDecimal); break; case id_minorNumber: Get_minorNumber().SetFormat(Integer::AsciiDecimal); csDot.Encode(buffer); break; default: break; } } void MimeVersion::PreDecode (Buffer& buffer) throw (DecodeError) { Get_majorNumber().SetFormat(Integer::AsciiDecimal); Get_minorNumber().SetFormat(Integer::AsciiDecimal); } void MimeVersion::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^[.]"); if (id == id_minorNumber) { reg_separator.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); } } void MinExpires::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_delta_sec ("^[0-9]+"); switch (id) { case id_deltaSec: reg_delta_sec.AssertMatch (buffer, this); SetHypFieldLength (id, reg_delta_sec.GetMatchedLength()); break; } } void Organization::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_organization ("^(" SIPREG_TEXT_UTF8_TRIM ")*"); switch (id) { case id_organization: reg_organization.AssertMatch (buffer, this); SetHypFieldLength (id, reg_organization.GetMatchedLength()); break; } } void Priority::PreDecodeField (int id, Buffer& buffer) throw (DecodeError){ static Regex reg_priority ("^" SIPREG_TOKEN); if (id == id_priorityValue){ reg_priority.AssertMatch(buffer, this); SetHypFieldLength(id, reg_priority.GetMatchedLength()); } } void RetryAfter::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csLeftPar, csSemi; csLeftPar.SetValue("("); csSemi.SetValue(";"); if(field_id == id_comment && IsPresent(id_comment)) { csLeftPar.Encode(buffer); } if(field_id == id_retryParams && IsPresent(id_retryParams)) { csSemi.Encode(buffer); } } void RetryAfter::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csRightPar; csRightPar.SetValue(")"); if(field_id == id_comment && IsPresent(id_comment)) { csRightPar.Encode(buffer); } } void RetryAfter::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_delta_sec ("^[0-9]+"); static Regex reg_comment ("^" SIPREG_COMMENT); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_deltaSec: reg_delta_sec.AssertMatch (buffer, this); SetHypFieldLength (id, reg_delta_sec.GetMatchedLength()); break; case id_comment: remove_whitespace(buffer); if (reg_comment.Match (buffer)) { SetHypFieldIsPresent(id, 1); SetHypFieldLength (id, reg_comment.GetMatchedLength() - 16); buffer.SetPosition(buffer.GetPosition() + 8); } else SetHypFieldIsPresent(id, 0); break; case id_retryParams: if (reg_separator.Match (buffer)) SetHypFieldIsPresent(id, 1); else SetHypFieldIsPresent(id, 0); break; } } void RetryAfter::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_parenthesis ("^[)]"); if (id == id_comment && IsPresent(id)) { reg_parenthesis.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); remove_whitespace(buffer); } } void Subject::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_summary ("^(" SIPREG_TEXT_UTF8_TRIM ")*"); switch (id) { case id_summary: reg_summary.AssertMatch (buffer, this); SetHypFieldLength (id, reg_summary.GetMatchedLength()); break; } } void ServerVal_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS; csWS.SetValue(" "); if(field_id != 0) { csWS.Encode(buffer); } } void ServerVal_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^((?:" SIPREG_TOKEN "(?:" SIPREG_SLASH SIPREG_TOKEN ")?)|" SIPREG_COMMENT ")"); reg_content.AssertMatch(buffer, this); SetHypFieldLength(reg_content.GetMatchedLength()); } void ServerVal_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_LWS); if (reg_separator.Match (buffer)) { reg_separator.MovePast (buffer); SetHypSize (GetSize() + 1); } else SetHypSize (-2); } void Supported::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_TOKEN); switch (id){ case id_optionsTags: if (reg_content.Match (buffer) || Get_optionsTags().GetSize() > 0) SetHypFieldIsPresent(id, 1); else SetHypFieldIsPresent(id, 0); break; } } void NameAddr::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csLeftAngle; csLeftAngle.SetValue("<"); if(field_id == id_addrSpec) { csLeftAngle.Encode(buffer); } } void NameAddr::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS, csRightAngle; csWS.SetValue(" "); csRightAngle.SetValue(">"); switch(field_id) { case id_displayName: if(IsPresent(id_displayName)) { csWS.Encode(buffer); } break; case id_addrSpec: csRightAngle.Encode(buffer); break; default: break; } } void NameAddr::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_display_name ("^" SIPREG_DISPLAY_NAME); static Regex reg_laquot = ("^<"); static Regex reg_uri = ("^[^\\r\\n]+"); remove_whitespace(buffer); switch (id){ case id_displayName: if (reg_display_name.Match(buffer)) { SetHypFieldIsPresent (id, 1); SetHypFieldLength (id, reg_display_name.GetMatchedLength()); } else { SetHypFieldIsPresent (id, 0); } break; case id_addrSpec: reg_laquot.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); reg_uri.AssertMatch(buffer, this); SetHypFieldLength (id, reg_uri.GetMatchedLength()); break; } } void NameAddr::PostDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_raquot ("^>"); reg_raquot.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); remove_whitespace(buffer); if (IsPresent (id_displayName)) { if (Get_displayName().GetLength() && (*Get_displayName().GetValueBin() == '"')) normalise_quoted_string (Get_displayName(), true); } } void SentProtocol::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSlash; csSlash.SetValue("/"); if(field_id != id_protocolName) { csSlash.Encode(buffer); } } void SentProtocol::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (id) { static Regex reg_slash ("^/"); reg_slash.AssertMatch (buffer, this); reg_slash.MovePast (buffer); } static Regex reg_sp ("^" SIPREG_TOKEN); reg_sp.AssertMatch (buffer, this); SetHypFieldLength (id, reg_sp.GetMatchedLength()); } void ViaBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_viaParams && IsPresent(id_viaParams)) { csSemi.Encode(buffer); } } void ViaBody::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS; csWS.SetValue(" "); if(field_id == id_sentProtocol) { csWS.Encode(buffer); } } void ViaBody::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_lws ("^" SIPREG_LWS); static Regex reg_semi ("^;"); switch (id) { case id_sentBy: reg_lws.AssertMatch (buffer, this); reg_lws.MovePast (buffer); break; case id_viaParams: SetHypFieldIsPresent (id, reg_semi.Match (buffer) ? 1 : 0); break; default: ; } } void ViaBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void ViaBody_List::PreDecode (Buffer& buffer) throw (DecodeError) { // we assume that we are decoding one field at once // multiple fields are handled by successively decoding // the via field several times in MessageHeader SetHypSize (GetSize() + 1); SetHypAppend (1); } void ViaBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { Regex reg_comma ("^" SIPREG_COMMA); if (reg_comma.Match(buffer)) { reg_comma.MovePast(buffer); SetHypSize (GetSize() + 1); } } void UndefinedHeader_List::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csCRLF; csCRLF.SetValue("\r\n"); csCRLF.Encode(buffer); } void UndefinedHeader_List::PreDecode (Buffer& buffer) throw (DecodeError) { // we assume that we are decoding one field at once // multiple fields are handled by successively decoding // the via field several times in MessageHeader SetHypSize (GetSize() + 1); SetHypAppend (1); } void UndefinedHeader::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csColon; csColon.SetValue(": "); if(field_id == id_headerName) { csColon.Encode(buffer); } } void UndefinedHeader::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_header_name ("^" SIPREG_TOKEN); // TODO: match properly UTF-8 characters // TODO: normalise the value ?... static Regex reg_header_value ("^" SIPREG_HCOLON "(([^\\r\\n]|" SIPREG_SWS ")*)"); switch (id) { case id_headerName: reg_header_name.AssertMatch (buffer, this); SetHypFieldLength (id, reg_header_name.GetMatchedLength()); break; case id_headerValue: reg_header_value.AssertMatch (buffer, this); reg_header_value.MoveAt (buffer, 1); SetHypFieldLength (id, reg_header_value.GetMatchedLength(1)); break; default: ; } } void UndefinedHeader::PostDecode (Buffer& buffer) throw (DecodeError) { normalise_escaped_string (Get_headerValue()); } void CallId::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (id == id_callid) { static Regex reg_cid ("^" SIPREG_WORD "(@" SIPREG_WORD ")*" ); reg_cid.AssertMatch(buffer, this); SetHypFieldLength (id, reg_cid.GetMatchedLength()); } } void CSeq::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS; csWS.SetValue(" "); switch(field_id) { case id_method: csWS.Encode(buffer); break; case id_seqNumber: Get_seqNumber().SetFormat(Integer::AsciiDecimal); break; default: break; } } void CSeq::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_method ("^" SIPREG_LWS "(" SIPREG_TOKEN ")"); switch (id) { case id_seqNumber: Get_seqNumber().SetFormat(Integer::AsciiDecimal); break; case id_method: reg_method.AssertMatch (buffer, this); reg_method.MoveAt (buffer, 1); SetHypFieldLength (id, reg_method.GetMatchedLength(1)); break; } } void ContentLength::PreEncode (Buffer& buffer) throw (EncodeError) { Get_len().SetFormat(Integer::AsciiDecimal); } void ContentLength::PreDecode (Buffer& buffer) throw (DecodeError) { Get_len().SetFormat(Integer::AsciiDecimal); } void ContentType::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_ctype ("^" SIPREG_TOKEN "/" SIPREG_TOKEN "(" SIPREG_SEMI SIPREG_M_PARAMETER ")*"); if (id == id_mediaType) { reg_ctype.AssertMatch (buffer, this); SetHypFieldLength (id, reg_ctype.GetMatchedLength()); } } #define SIP_MESSAGE_CODET(msgname) \ void msgname::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) \ { \ switch (id) { \ case id_msgHeader: \ { \ /* decide if we have to decode the message body and how to decode it */ \ MessageHeader& hdr = Get_msgHeader(); \ int content_length = hdr.IsPresent (MessageHeader::id_contentLength) ? hdr.Get_contentLength().Get_len().GetValue() : 0; \ if (content_length == 0) { \ /* no message body */ \ if (hdr.IsPresent (MessageHeader::id_contentType)) \ throw DecodeError (this, "the Content-Type field must not be present if the content length is null\n"); \ \ SetHypFieldIsPresent (id_messageBody, 0); \ } else if (content_length > 0) { \ /* message body present */ \ if (!hdr.IsPresent (MessageHeader::id_contentType)) \ throw DecodeError (this, "the Content-Type field must be present if the content length is not null\n"); \ \ SetHypFieldIsPresent (id_messageBody, 1); \ MessageBody::SetHypLength (content_length * 8); \ const char* content_type = hdr.Get_contentType().Get_mediaType().GetValue(); \ if (strcmp (content_type, "application/sdp") == 0) { \ MessageBody::SetHypChosenId (MessageBody::id_sdpMessageBody); \ } else { \ /* decode as plain text by default */ \ MessageBody::SetHypChosenId (MessageBody::id_textplain); \ } \ } else { \ throw DecodeError (this, "Content-Length must not be a negative number\n"); \ } \ SetHypFieldIsPresent (id_payload, 0); \ break; \ } \ case id_payload: \ if (buffer.GetBitsLeft()) { \ DecodeError ex(this); \ ex.Msg() << "buffer not fully decoded (" << buffer.GetBitsLeft()/8 << " remaining bytes)" << std::endl; \ throw ex; \ } \ Get_payload().Get_payloadlength().SetValue(buffer.GetLength() / 8); \ Get_payload().Get_payloadvalue().SetValueBin(buffer.GetValueBin(), buffer.GetLength()); \ \ /* replace undisplayable characters with '?' */ \ Charstring& payload = Get_payload().Get_payloadvalue(); \ int byte_length = buffer.GetLength() / 8; \ for (int i=0 ; i(buffer.GetValueBin()), buffer.GetLength()/8); \ std::cerr << "###################################################################################" << std::endl; \ /* tell t3devkit to ignore silently the message */ \ throw DecodeIgnoreMessage(e.mVar); \ } SIP_MESSAGE_CODET (Response) SIP_MESSAGE_CODET_ERROR (Response) SIP_MESSAGE_CODET (Request) SIP_MESSAGE_CODET_ERROR (Request) SIP_MESSAGE_CODET (REGISTER_Request) SIP_MESSAGE_CODET_ERROR (REGISTER_Request) SIP_MESSAGE_CODET (INVITE_Request) SIP_MESSAGE_CODET_ERROR (INVITE_Request) SIP_MESSAGE_CODET (OPTIONS_Request) SIP_MESSAGE_CODET_ERROR (OPTIONS_Request) SIP_MESSAGE_CODET (BYE_Request) SIP_MESSAGE_CODET_ERROR (BYE_Request) SIP_MESSAGE_CODET (CANCEL_Request) SIP_MESSAGE_CODET_ERROR (CANCEL_Request) SIP_MESSAGE_CODET (ACK_Request) SIP_MESSAGE_CODET_ERROR (ACK_Request) SIP_MESSAGE_CODET (PRACK_Request) SIP_MESSAGE_CODET_ERROR (PRACK_Request) SIP_MESSAGE_CODET (NOTIFY_Request) SIP_MESSAGE_CODET_ERROR (NOTIFY_Request) SIP_MESSAGE_CODET (SUBSCRIBE_Request) SIP_MESSAGE_CODET_ERROR (SUBSCRIBE_Request) SIP_MESSAGE_CODET (PUBLISH_Request) SIP_MESSAGE_CODET_ERROR (PUBLISH_Request) SIP_MESSAGE_CODET (UPDATE_Request) SIP_MESSAGE_CODET_ERROR (UPDATE_Request) SIP_MESSAGE_CODET (REFER_Request) SIP_MESSAGE_CODET_ERROR (REFER_Request) SIP_MESSAGE_CODET (MESSAGE_Request) SIP_MESSAGE_CODET_ERROR (MESSAGE_Request) SIP_MESSAGE_CODET (INFO_Request) SIP_MESSAGE_CODET_ERROR (INFO_Request) void OptionTag_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void OptionTag_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void OptionTag_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_TOKEN); bool bMandatory = true; Variable* parent = GetParent(); if (parent != NULL) { const char * pszParName = parent->GetTypeName(); if (strcmp(pszParName, "Supported") == 0) bMandatory = false; } if (bMandatory || GetSize() == 0) reg_content.AssertMatch(buffer, this); else if (!reg_content.Match (buffer)) { SetHypSize (-2); return; } SetHypFieldLength(reg_content.GetMatchedLength()); } void OptionTag_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_content ("^" SIPREG_TOKEN); if (detect_comma (buffer) && reg_content.Match (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void RouteBody_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void RouteBody_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void RouteBody_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void RouteBody::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_rrParam && IsPresent(id_rrParam)) { csSemi.Encode(buffer); } } void RouteBody::PreDecodeField(int id, Buffer& buffer) throw (DecodeError) { static Regex reg_semi ("^;"); if (id == id_rrParam) { SetHypFieldIsPresent (id, reg_semi.Match(buffer) ? 1 : 0); } } void Timestamp::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS; csWS.SetValue(" "); switch(field_id) { case id_delay: if(IsPresent(id_delay)) { csWS.Encode(buffer); } break; default: break; } } void Timestamp::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_LWS); switch (id) { case id_timeValue: SetHypFieldIsPresent (id, 1); //always present (mandatory in BNF) break; case id_delay: if (reg_separator.Match (buffer)) { reg_separator.MovePast (buffer); SetHypFieldIsPresent (id, 1); } else SetHypFieldIsPresent (id, 0); break; } } void TimeValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csDot; csDot.SetValue("."); switch(field_id) { case id_majorDigit: Get_majorDigit().SetFormat(Integer::AsciiDecimal); break; case id_minorDigit: Get_minorDigit().SetFormat(Integer::AsciiDecimal); csDot.Encode(buffer); break; default: break; } } void TimeValue::PreDecode (Buffer& buffer) throw (DecodeError) { Get_majorDigit().SetFormat(Integer::AsciiDecimal); Get_minorDigit().SetFormat(Integer::AsciiDecimal); } void TimeValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^[.]"); static Regex reg_digits ("^[0-9]+"); switch (id) { case id_minorDigit: SetHypFieldIsPresent (id, 0); if (reg_separator.Match (buffer)) { reg_separator.MovePast( buffer); if (reg_digits.Match (buffer)) SetHypFieldIsPresent(id, 1); } break; } } void WarningValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void WarningValue_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void WarningValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void WarningValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS, csDoubleQuote; csWS.SetValue(" "); csDoubleQuote.SetValue("\""); switch(field_id) { case id_warnCode: Get_warnCode().SetFormat(Integer::AsciiDecimal); break; case id_warnText: csWS.Encode(buffer); csDoubleQuote.Encode(buffer); break; case id_warnAgent: csWS.Encode(buffer); break; } } void WarningValue::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csDoubleQuote; csDoubleQuote.SetValue("\""); if(field_id == id_warnText) { csDoubleQuote.Encode(buffer); } } void WarningValue::PreDecode (Buffer& buffer) throw (DecodeError) { Get_warnCode().SetFormat(Integer::AsciiDecimal); } void WarningValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^[ ]"); static Regex reg_text ("^" SIPREG_QUOTED_STRING); switch (id) { case id_warnAgent: reg_separator.AssertMatch (buffer, this); reg_separator.MovePast (buffer); break; case id_warnText: reg_separator.AssertMatch (buffer, this); reg_separator.MovePast (buffer); reg_text.AssertMatch (buffer, this); buffer.SetPosition(buffer.GetPosition() + 8); // remove starting quota SetHypFieldLength (id, reg_text.GetMatchedLength() - 16); break; } } void WarningValue::PostDecode (Buffer& buffer) throw (DecodeError) { buffer.SetPosition(buffer.GetPosition() + 8); // remove ending quota normalise_quoted_string (Get_warnText()); } void WarnAgent::PreDecode (Buffer& buffer) throw (DecodeError) { static Regex reg_host ("^" SIPREG_HOST "([:][0-9]+)?"); static Regex reg_pseudonym ("^" SIPREG_TOKEN); int nLen1 = -1; int nLen2 = -1; if (reg_host.Match (buffer)) nLen1 = reg_host.GetMatchedLength(); if (reg_pseudonym.Match (buffer)) nLen2 = reg_pseudonym.GetMatchedLength(); if (nLen2 > nLen1) { SetHypChosenId (id_pseudonym); SetHypFieldLength (id_pseudonym, nLen2); } else SetHypChosenId (id_hostPort); } void RSeq::PreEncode (Buffer& buffer) throw (EncodeError) { Get_responseNum().SetFormat(Integer::AsciiDecimal); } void RSeq::PreDecode (Buffer& buffer) throw (DecodeError) { Get_responseNum().SetFormat(Integer::AsciiDecimal); } void RAck::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csWS; csWS.SetValue(" "); switch(field_id) { case id_responseNum: Get_responseNum().SetFormat(Integer::AsciiDecimal); break; case id_seqNumber: Get_seqNumber().SetFormat(Integer::AsciiDecimal); case id_method: csWS.Encode(buffer); break; default: break; } } void RAck::PreDecode (Buffer& buffer) throw (DecodeError) { Get_responseNum().SetFormat(Integer::AsciiDecimal); Get_seqNumber().SetFormat(Integer::AsciiDecimal); } void RAck::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^[ ]"); static Regex reg_method ("^" SIPREG_TOKEN); switch (id) { case id_seqNumber: reg_separator.AssertMatch (buffer, this); reg_separator.MovePast (buffer); break; case id_method: reg_separator.AssertMatch (buffer, this); reg_separator.MovePast (buffer); reg_method.AssertMatch (buffer, this); SetHypFieldLength (id, reg_method.GetMatchedLength()); break; } } void EventType_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void EventType_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void EventType_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_event ("^" SIPREG_TOKEN); reg_event.AssertMatch (buffer, this); SetHypFieldLength (reg_event.GetMatchedLength()); } void EventType_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void Event::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_eventParams && IsPresent(id_eventParams)) { csSemi.Encode(buffer); } } void Event::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_event ("^" SIPREG_TOKEN); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_eventType: reg_event.AssertMatch (buffer, this); SetHypFieldLength (id, reg_event.GetMatchedLength()); break; case id_eventParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void SubscriptionState::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_substateParams && IsPresent(id_substateParams)) { csSemi.Encode(buffer); } } void SubscriptionState::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_substate ("^" SIPREG_TOKEN); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_subState: reg_substate.AssertMatch (buffer, this); SetHypFieldLength (id, reg_substate.GetMatchedLength()); break; case id_substateParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void PMediaAuthorization_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void PMediaAuthorization_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void PMediaAuthorization_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_media_authorization ("^[" SIPCHARS_HEXA "]+"); reg_media_authorization.AssertMatch (buffer, this); SetHypFieldLength (reg_media_authorization.GetMatchedLength()); } void PMediaAuthorization_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void PrivacyValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id != 0) { csSemi.Encode(buffer); } } void PrivacyValue_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_privacy ("^" SIPREG_TOKEN); reg_privacy.AssertMatch (buffer, this); SetHypFieldLength (reg_privacy.GetMatchedLength()); } void PrivacyValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_semi (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void PAssertedIDValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void PAssertedIDValue_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void PAssertedIDValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void PPreferredIDValue_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void PPreferredIDValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void ReasonValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_reasonParams && IsPresent(id_reasonParams)) { csSemi.Encode(buffer); } } void ReasonValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_token: reg_token.AssertMatch (buffer, this); SetHypFieldLength (id, reg_token.GetMatchedLength()); break; case id_reasonParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void ReasonValues::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void PathValues::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void ReasonValues::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void ReasonValues::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void PathValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_rrParam && IsPresent(id_rrParam)) { csSemi.Encode(buffer); } } void PathValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_rrParam: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void PathValues::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void PathValues::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void SecurityMechanism::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_mechParams && IsPresent(id_mechParams)) { csSemi.Encode(buffer); } } void SecurityMechanism::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_mechName: reg_token.AssertMatch (buffer, this); SetHypFieldLength (id, reg_token.GetMatchedLength()); break; case id_mechParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void SecurityMechanism_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void SecurityMechanism_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void SecurityMechanism_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void NameAddrParam::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_genericParams && IsPresent(id_genericParams)) { csSemi.Encode(buffer); } } void NameAddrParam::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_genericParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void NameAddrParam_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void NameAddrParam_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void NameAddrParam_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void VnetworkSpec::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_genericParams && IsPresent(id_genericParams)) { csSemi.Encode(buffer); } } void VnetworkSpec::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^(" SIPREG_TOKEN ")|(" SIPREG_QUOTED_STRING ")"); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_vNetworkSpecToken: reg_token.AssertMatch (buffer, this); SetHypFieldLength (id, reg_token.GetMatchedLength()); break; case id_genericParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void VnetworkSpec_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void VnetworkSpec_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void VnetworkSpec_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void PAccessNetworkInfo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_genericParams && IsPresent(id_genericParams)) { csSemi.Encode(buffer); } } void PAccessNetworkInfo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_accessType: reg_token.AssertMatch (buffer, this); SetHypFieldLength (id, reg_token.GetMatchedLength()); break; case id_genericParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void PChargingFunctionAddresses::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); switch (id) { case id_chargeAddrParams: SetHypFieldIsPresent (id, reg_token.Match (buffer) ? 1 : 0); break; } } void PChargingVector::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); switch (id) { case id_chargeParams: SetHypFieldIsPresent (id, reg_token.Match (buffer) ? 1 : 0); break; } } void ReferTo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_referToParams && IsPresent(id_referToParams)) { csSemi.Encode(buffer); } } void ReferTo::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_referToParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void AcRcValue_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void AcRcValue_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void AcRcValue_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void AcRcValue::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_acRcParams && IsPresent(id_acRcParams)) { csSemi.Encode(buffer); } } void AcRcValue::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_wildcard ("^[*]"); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_wildcard: reg_wildcard.AssertMatch (buffer, this); SetHypFieldLength (id, reg_wildcard.GetMatchedLength()); break; case id_acRcParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void Replaces::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_fieldName && IsPresent(id_fieldName)) { csSemi.Encode(buffer); } } void Replaces::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_fieldName: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void ReferredBy::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_referredbyIdParams && IsPresent(id_referredbyIdParams)) { csSemi.Encode(buffer); } } void ReferredBy::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_referredbyIdParams: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } /* Nothing to do void UserToUser::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { } void UserToUser::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { }*/ void MinSE::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_minSeParam && IsPresent(id_minSeParam)) { csSemi.Encode(buffer); } } void MinSE::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_delta_sec ("^[0-9]+"); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_deltaSec: reg_delta_sec.AssertMatch (buffer, this); SetHypFieldLength (id, reg_delta_sec.GetMatchedLength()); break; case id_minSeParam: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void IntegerList::PreEncode (Buffer& buffer) throw (EncodeError) { Charstring csIndexEqual; csIndexEqual.SetValue("index="); csIndexEqual.Encode(buffer); } void IntegerList::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csDot; csDot.SetValue("."); if(field_id != 0) { csDot.Encode(buffer); } GetField(field_id).SetFormat(Integer::AsciiDecimal); } void IntegerList::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { SetSize (GetSize() + 1); GetField(id).SetFormat(Integer::AsciiDecimal); } void IntegerList::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { Regex reg_dot ("^[\\x2E]"); if (detect_separator(reg_dot, buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void HistoryInfoEntry::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csSemi; csSemi.SetValue(";"); if(field_id == id_hiIndex && IsPresent(id_hiIndex)) { csSemi.Encode(buffer); } if(field_id == id_hiExtention && IsPresent(id_hiExtention)) { csSemi.Encode(buffer); } } void HistoryInfoEntry::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_index ("^" SIPREG_SEMI "[Ii][Nn][Dd][Ee][Xx][=]"); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_hiIndex: if (reg_index.Match (buffer)) { reg_index.MovePast (buffer); SetHypFieldIsPresent (id, 1); } else SetHypFieldIsPresent (id, 0); break; case id_hiExtention: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } void HistoryInfo_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void HistoryInfo_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void HistoryInfo_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void EM_List::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { Charstring csComma; csComma.SetValue(","); if(field_id != 0) { csComma.Encode(buffer); } } void EM_List::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); if (GetSize() == 0) reg_token.AssertMatch(buffer, this); else if (!reg_token.Match(buffer)) { SetHypSize(-2); return; } SetHypFieldLength(reg_token.GetMatchedLength()); } void EM_List::PreDecode (Buffer& buffer) throw (DecodeError) { SetHypSize (GetSize() + 1); SetHypAppend (1); } void EM_List::PostDecodeField (int id, Buffer& buffer) throw (DecodeError) { if (detect_comma (buffer)) SetHypSize (GetSize() + 1); else SetHypSize (-2); } void PEarlyMedia::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); switch (id) { case id_em_param: if (reg_token.Match (buffer) || Get_em_param().GetSize() > 0) { SetHypFieldIsPresent (id, 1); } else SetHypFieldIsPresent (id, 0); break; } } /* UserToUser: Nothing to do void UserToUser::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError) { } void UserToUser::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { }*/ void PAssertedService::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_token ("^" SIPREG_TOKEN); switch (id) { case id_pAssertedServiceValue: reg_token.AssertMatch (buffer, this); SetHypFieldLength(id, reg_token.GetMatchedLength()); break; } } void MessageBody::PreEncode (Buffer& buffer) throw (EncodeError) { switch (GetChosenId()) { case id_xmlBody: case id_xmlMessage: case id_mimeMessageBody: { std::string message ("unsupported field '"); message += GetChosenFieldName(); message += '\n'; throw EncodeError (this, message); } break; } } void SessionExpires::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) { static Regex reg_delta_sec ("^[0-9]+"); static Regex reg_separator ("^" SIPREG_SEMI); switch (id) { case id_deltaSec: reg_delta_sec.AssertMatch (buffer, this); SetHypFieldLength (id, reg_delta_sec.GetMatchedLength()); break; case id_seParam: SetHypFieldIsPresent (id, reg_separator.Match (buffer) ? 1 : 0); break; } } }} // namespaces