📄 osip_message_parse.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 <osipparser2/osip_port.h>#include <osipparser2/osip_parser.h>#include "parser.h"static void osip_util_replace_all_lws (char *sip_message);static int osip_message_set__header (osip_message_t * sip, const char *hname, const char *hvalue);static int msg_handle_multiple_values (osip_message_t * sip, char *hname, char *hvalue);static int msg_headers_parse (osip_message_t * sip, const char *start_of_header, const char **body);static int msg_osip_body_parse (osip_message_t * sip, const char *start_of_buf, const char **next_body);static int msg_osip_body_parse2 (osip_message_t * sip, const char *start_of_buf, const char **next_body, size_t length);static int__osip_message_startline_parsereq (osip_message_t * dest, const char *buf, const char **headers){ const char *p1; const char *p2; char *requesturi; int i; dest->sip_method = NULL; dest->status_code = 0; dest->reason_phrase = 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->sip_method = (char *) osip_malloc (p2 - buf + 1); osip_strncpy (dest->sip_method, 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==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Uncompliant request-uri\n")); osip_free(dest->sip_method); dest->sip_method = NULL; return -1; } if (p1 - p2 < 2) { osip_free(dest->sip_method); dest->sip_method = NULL; return -1; } requesturi = (char *) osip_malloc (p1 - p2); osip_strncpy (requesturi, p2 + 1, (p1 - p2 - 1)); osip_clrspace (requesturi); osip_uri_init (&(dest->req_uri)); i = osip_uri_parse (dest->req_uri, requesturi); osip_free (requesturi); if (i != 0) { osip_free(dest->sip_method); dest->sip_method = NULL; osip_uri_free(dest->req_uri); dest->req_uri = NULL; return -1; } /* find the the version and the beginning of headers */ { const 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")); osip_free(dest->sip_method); dest->sip_method = NULL; osip_uri_free(dest->req_uri); dest->req_uri = NULL; return -1; } } if (hp - p1 < 2) { osip_free(dest->sip_method); dest->sip_method = NULL; osip_uri_free(dest->req_uri); dest->req_uri = NULL; return -1; } dest->sip_version = (char *) osip_malloc (hp - p1); osip_strncpy (dest->sip_version, p1 + 1, (hp - p1 - 1)); if (0!=osip_strcasecmp(dest->sip_version, "SIP/2.0")) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Wrong version number\n")); } hp++; if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0])) hp++; (*headers) = hp; } return 0;}static int__osip_message_startline_parseresp (osip_message_t * dest, const char *buf, const char **headers){ const char *statuscode; const char *reasonphrase; dest->req_uri = NULL; dest->sip_method = NULL; *headers = buf; statuscode = strchr (buf, ' '); /* search for first SPACE */ if (statuscode == NULL) return -1; dest->sip_version = (char *) osip_malloc (statuscode - (*headers) + 1); osip_strncpy (dest->sip_version, *headers, statuscode - (*headers)); reasonphrase = strchr (statuscode + 1, ' '); if (reasonphrase==NULL) { osip_free(dest->sip_version); dest->sip_version = NULL; return -1; } /* dest->status_code = (char *) osip_malloc (reasonphrase - statuscode); */ /* osip_strncpy (dest->status_code, statuscode + 1, reasonphrase - statuscode - 1); */ if (sscanf (statuscode + 1, "%d", &dest->status_code) != 1) { /* Non-numeric status code */ return -1; } { const 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->reason_phrase = (char *) osip_malloc (hp - reasonphrase); osip_strncpy (dest->reason_phrase, reasonphrase + 1, hp - reasonphrase - 1); hp++; if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0])) hp++; (*headers) = hp; } return 0;}static int__osip_message_startline_parse (osip_message_t * dest, const char *buf, const char **headers){ if (0 == strncmp ((const char *) buf, (const char *) "SIP/", 4)) return __osip_message_startline_parseresp (dest, buf, headers); else return __osip_message_startline_parsereq (dest, buf, headers);}int__osip_find_next_occurence (const char *str, const char *buf, const 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 (buf, str); if (NULL == (*index_of_str)) return -1; return 0;}/* This method replace all LWS with SP located before the initial CRLFCRLF found or the end of the string.*/static voidosip_util_replace_all_lws (char *sip_message){ const char *end_of_message; char *tmp; if (sip_message == NULL) return; end_of_message = sip_message + strlen (sip_message); tmp = sip_message; for (; tmp < end_of_message; tmp++) { if (('\0' == tmp[0]) || ('\0' == tmp[1]) || ('\0' == tmp[2]) || ('\0' == tmp[3])) return; if ((('\r' == tmp[0]) && ('\n' == tmp[1]) && ('\r' == tmp[2]) && ('\n' == tmp[3])) || (('\r' == tmp[0]) && ('\r' == tmp[1])) || (('\n' == tmp[0]) && ('\n' == tmp[1]))) return; /* end of message */ if ((('\r' == tmp[0]) && ('\n' == tmp[1]) && ((' ' == tmp[2]) || ('\t' == tmp[2]))) || (('\r' == tmp[0]) && ((' ' == tmp[1]) || ('\t' == tmp[1]))) || (('\n' == tmp[0]) && ((' ' == tmp[1]) || ('\t' == tmp[1])))) { /* replace line end and TAB symbols by SP */ tmp[0] = ' '; tmp[1] = ' '; tmp = tmp + 2; /* replace all following TAB symbols */ for (; ('\t' == tmp[0] || ' ' == tmp[0]);) { tmp[0] = ' '; tmp++; } } }}int__osip_find_next_crlf (const char *start_of_header, const char **end_of_header){ const char *soh = start_of_header; *end_of_header = NULL; /* AMD fix */ 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 case 2 or 3: CR or LF is the separator */ soh = soh + 1; /* VERIFY if TMP is the end of header or LWS. */ /* LWS are extra SP, HT, CR and LF contained in headers. */ if ((' ' == soh[1]) || ('\t' == soh[1])) { /* From now on, incoming message that potentially contains LWS must be processed with -> void osip_util_replace_all_lws(char *) This is because the parser methods does not support detection of LWS inside. */ OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_BUG, NULL, "Message that contains LWS must be processed with osip_util_replace_all_lws(char *tmp) before being parsed.\n")); return -1; } *end_of_header = soh + 1; return 0;}int__osip_find_next_crlfcrlf (const char *start_of_part, const char **end_of_part){ const char *start_of_line; const char *end_of_line; int i; start_of_line = start_of_part; for (;;) { i = __osip_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; }}static intosip_message_set__header (osip_message_t * sip, const char *hname, const char *hvalue){ int my_index; if (hname == NULL) return -1; /* some headers are analysed completely */ /* this method is used for selective parsing */ my_index = __osip_message_is_known_header (hname); if (my_index >= 0) /* ok */ { int ret; ret = __osip_message_call_method (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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -