📄 msg_parser.c
字号:
/* The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-) Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <stdio.h>#include <stdlib.h>#include <osip/smsg.h>#include <osip/port.h>#include "msg.h"static intstartline_parsereq (startline_t * dest, char *buf, char **headers){ char *p1; char *p2; char *requesturi; int i; dest->sipmethod = NULL; dest->statuscode = NULL; dest->reasonphrase = NULL; /* The first token is the method name: */ p2 = strchr (buf, ' '); if (p2 == NULL) return -1; if (p2-buf==0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "No space allowed here\n")); return -1; } dest->sipmethod = (char *) smalloc (p2 - buf + 1); sstrncpy (dest->sipmethod, buf, p2 - buf); /* The second token is a sip-url or a uri: */ p1 = strchr (p2 + 2, ' '); /* no space allowed inside sip-url */ if (p1 - p2 < 2) return -1; requesturi = (char *) smalloc (p1 - p2); sstrncpy (requesturi, p2 + 1, (p1 - p2 - 1)); sclrspace (requesturi); url_init (&(dest->rquri)); i = url_parse (dest->rquri, requesturi); sfree (requesturi); if (i == -1) return -1; /* find the the version and the beginning of headers */ { char *hp = p1; while ((*hp != '\r') && (*hp != '\n')) { if (*hp) hp++; else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "No crlf found\n")); return -1; } } if (hp - p1 < 2) return -1; dest->sipversion = (char *) smalloc (hp - p1); sstrncpy (dest->sipversion, p1 + 1, (hp - p1 - 1)); hp++; if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0])) hp++; (*headers) = hp; } return 0;}static intstartline_parseresp (startline_t * dest, char *buf, char **headers){ char *statuscode; char *reasonphrase; dest->rquri = NULL; dest->sipmethod = NULL; *headers = buf; statuscode = strchr (buf, ' '); /* search for first SPACE */ if (statuscode == NULL) return -1; dest->sipversion = (char *) smalloc (statuscode - (*headers) + 1); sstrncpy (dest->sipversion, *headers, statuscode - (*headers)); reasonphrase = strchr (statuscode + 1, ' '); dest->statuscode = (char *) smalloc (reasonphrase - statuscode); sstrncpy (dest->statuscode, statuscode + 1, reasonphrase - statuscode - 1); { char *hp = reasonphrase; while ((*hp != '\r') && (*hp != '\n')) { if (*hp) hp++; else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "No crlf found\n")); return -1; } } dest->reasonphrase = (char *) smalloc (hp - reasonphrase); sstrncpy (dest->reasonphrase, reasonphrase + 1, hp - reasonphrase - 1); hp++; if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0])) hp++; (*headers) = hp; } return 0;}/* return size of request URI */static intmsg_startline_parse (startline_t * dest, char *buf, char **headers){ if (0 == strncmp ((const char *) buf, (const char *) "SIP/", 4)) return startline_parseresp (dest, buf, headers); else return startline_parsereq (dest, buf, headers);}intfind_next_occurence (char *str, char *buf, char **index_of_str){ *index_of_str = NULL; /* AMD fix */ if ((NULL == str) || (NULL == buf)) return -1; /* TODO? we may prefer strcasestr instead of strstr? */ *index_of_str = strstr ((const char *) buf, (const char *) str); if (NULL == (*index_of_str)) return -1; return 0;}intfind_next_crlf (char *start_of_header, char **end_of_header){ char *tmp; *end_of_header = NULL; /* AMD fix */ for (;;) { int leol = 1; /* number of line-end symbols: */ /* if CR or LF =1, if CRLF =2 */ char *soh = start_of_header; while (('\r' != *soh) && ('\n' != *soh)) { if (*soh) soh++; else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Final CRLF is missing\n")); return -1; } } if (('\r' == soh[0]) && ('\n' == soh[1])) { /* case 1: CRLF is the separator */ tmp = soh + 1; leol = 2; } else tmp = soh; /* case 2 or 3: CR or LF is the separator */ /* VERIFY if TMP is the end of header or LWS. */ /* LWS are extra SP, HT, CR and LF contained in headers. */ if ((' ' == tmp[1]) || ('\t' == tmp[1])) { /* AMD fix: SPECIAL case! for people who add extra spaces */ /* with no meaning at the end of the body of SIP messages? */ /* if this occur before the body, this is an error case */ /* because the last header of a message MUST end with a */ /* CRLFCRLF (not only CRLF). I prefer to assume that buggy */ /* implementation exists... :( */ char *extraspaces = tmp + 2; /* replace line end and TAB symbols by SP */ tmp[1] = ' '; tmp[0] = ' '; if (2 == leol) tmp[-1] = ' '; for (;;) { /* this is for line ending with '\cr\lf\t ' (i.e more than one space after tab) */ if (' ' == *extraspaces) extraspaces++; else if ('\t' == *extraspaces) { *extraspaces = ' '; extraspaces++; } else if ('\0' == *extraspaces) { tmp[1] = '\0'; /* this is the real limit of SIP message */ *end_of_header = tmp + 1; return 0; } else break; } /* YES, this is LWS extra characters */ /* restart search of the end of headers */ start_of_header = extraspaces; } else { *end_of_header = tmp + 1; /* beggining of next header */ return 0; } }}intfind_next_crlfcrlf (char *start_of_part, char **end_of_part){ char *start_of_line; char *end_of_line; int i; start_of_line = start_of_part; for (;;) { i = find_next_crlf (start_of_line, &end_of_line); if (i == -1) { /* error case??? no end of mesage found */ OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Final CRLF is missing\n")); return -1; } if ('\0' == end_of_line[0]) { /* error case??? no end of message found */ OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Final CRLF is missing\n")); return -1; } else if ('\r' == end_of_line[0]) { if ('\n' == end_of_line[1]) end_of_line++; *end_of_part = end_of_line + 1; return 0; } else if ('\n' == end_of_line[0]) { *end_of_part = end_of_line + 1; return 0; } start_of_line = end_of_line; }}intmsg_set_header (sip_t * sip, char *hname, char *hvalue){ int my_index; if (hname == NULL) return -1; stolowercase (hname); /* some headers are analysed completely */ /* this method is used for selective parsing */ my_index = parser_isknownheader (hname); if (my_index >= 0) /* ok */ { int ret; ret = parser_callmethod (my_index, sip, hvalue); if (ret == -1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not set header: \"%s\" %s\n", hname, hvalue)); return -1; } return 0; } /* unknownheader */ if (msg_setheader (sip, hname, hvalue) == -1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not set unknown header\n")); return -1; } return 0;}intmsg_handle_multiple_values (sip_t * sip, char *hname, char *hvalue){ int i; char *ptr; /* current location of the search */ char *comma; /* This is the separator we are elooking for */ char *beg; /* beg of a header */ char *end; /* end of a header */ char *quote1; /* first quote of a pair of quotes */ char *quote2; /* second quuote of a pair of quotes */ beg = hvalue; end = NULL; ptr = hvalue; if (hvalue == NULL) { i = msg_set_header (sip, hname, hvalue); if (i == -1) return -1; return 0; } comma = strchr (ptr, ','); stolowercase (hname); if (comma == NULL || (strncmp (hname, "date", 4) == 0 && strlen (hname) == 4 ) || strncmp (hname, "organization", 12) == 0 || (strncmp (hname, "to", 2) == 0 && strlen (hname) == 2) || (strncmp (hname, "from", 4) == 0 && strlen (hname) == 4) /* AMD: BUG fix */ || strncmp (hname, "call-id", 7) == 0 || (strncmp (hname, "cseq", 4) == 0 && strlen (hname) == 4) /* AMD: BUG fix */ || strncmp (hname, "subject", 7) == 0 || strncmp (hname, "user-agent", 10) == 0 || strncmp (hname, "server", 6) == 0 || strncmp (hname, "www-authenticate", 16) == 0 /* AMD: BUG fix */ || strncmp (hname, "authentication-info", 19) == 0 || strncmp (hname, "proxy-authenticate", 20) == 0 || strncmp (hname, "proxy-authorization", 19) == 0 || strncmp (hname, "proxy-authentication-info", 25) == 0 /* AMD: BUG fix */ || strncmp (hname, "authorization", 13) == 0) /* there is no multiple header! likely */ /* to happen most of the time... */ /* or hname is a TEXT-UTF8-TRIM and may */ /* contain a comma. this is not a separator */ /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */ { i = msg_set_header (sip, hname, hvalue); if (i == -1) return -1; return 0; } quote2 = NULL; while (comma != NULL) { quote1 = quote_find (ptr); if (quote1 != NULL) { quote2 = quote_find (quote1 + 1); if (quote2 == NULL) return -1; /* quotes comes by pair */ ptr = quote2 + 1; } if ((quote1 == NULL) || (quote1 > comma)) { end = comma; comma = strchr (comma + 1, ','); ptr = comma + 1; } else if ((quote1 < comma) && (quote2 < comma)) { /* quotes are located before the comma, */ /* continue the search for next quotes */ ptr = quote2 + 1; } else if ((quote1 < comma) && (comma < quote2)) { /* if comma is inside the quotes... */ /* continue with the next comma. */ ptr = quote2 + 1; comma = strchr (ptr, ','); if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ if (strlen (beg) < 2) return 0; /* empty header */ sclrspace (beg); i = msg_set_header (sip, hname, beg); if (i == -1) return -1; return 0; } } if (end != NULL) { char *avalue; if (end - beg + 1 < 2) return -1; avalue = (char *) smalloc (end - beg + 1); sstrncpy (avalue, beg, end - beg); sclrspace (avalue); /* really store the header in the sip structure */ i = msg_set_header (sip, hname, avalue); sfree (avalue); if (i == -1) return -1; beg = end + 1; end = NULL; if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ if (strlen (beg) < 2) return 0; /* empty header */ sclrspace (beg); i = msg_set_header (sip, hname, beg); if (i == -1) return -1; return 0; } } } return -1; /* if comma is NULL, we should have already return 0 */}/* set all headers */intmsg_headers_parse (sip_t * sip, char *start_of_header, char **body){ char *colon_index; /* index of ':' */ char *hname;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -