📄 sip_parser.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * 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., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@ingroup sip_parser * @CFILE sip_parser.c * * SIP parser. * * @author Pekka Pessi <Pekka.Pessi@nokia.com>. * * @date Created: Thu Oct 5 14:01:24 2000 ppessi */#include "config.h"/* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */#define MSG_PUB_T struct sip_s#define MSG_HDR_T union sip_header_u#include <sofia-sip/su_tagarg.h>#include "sofia-sip/sip_parser.h"#include <sofia-sip/msg_mclass.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <assert.h>#include <limits.h>#ifndef UINT32_MAX#define UINT32_MAX (0xffffffffU)#endif/** Version of the SIP module */char const sip_parser_version[] = VERSION;/** SIP version 2.0. */char const sip_version_2_0[] = "SIP/2.0";/** Default message class */extern msg_mclass_t sip_mclass[];static msg_mclass_t const *_default = sip_mclass;/** Return a built-in SIP parser object. */msg_mclass_t const *sip_default_mclass(void){ return _default;}/** Update the default SIP parser. * * Use the extended SIP parser as default one. * * If the applications want to use headers added after @VERSION_1_12_5, * they should call this function before doing any other initialization, e.g., * @code * su_init(); * if (sip_update_default_mclass(sip_extend_mclass(NULL)) < 0) { * su_deinit(); * exit(2); * } * @endcode * * The default parser is not extended because it may break the old * applications looking for extension headers from sip_unknown list. * * @retval 0 when successful * @retval -1 upon an error * * @sa sip_extend_mclass() * * @NEW_1_12_7. */int sip_update_default_mclass(msg_mclass_t const *mclass){ if (mclass == NULL) return -1; _default = mclass; return 0;}/**Extend SIP parser class with extension headers. * * Extend given SIP parser class with extension headers. If the given parser * (message class) is the default one or NULL, make a clone of default * parser before extending it. * * @param input pointer to a SIP message class (may be NULL) * * @return Pointer to extended mclass, or NULL upon an error. * * @sa * @AlertInfo, * @ReplyTo, * @RemotePartyId, * @PAssertedIdentity, * @PPreferredIdentity, * @SuppressBodyIfMatch, * @SuppressNotifyIfMatch * * @NEW_1_12_7. */msg_mclass_t *sip_extend_mclass(msg_mclass_t *input){ msg_mclass_t *mclass; if (input == NULL || input == _default) mclass = msg_mclass_clone(_default, 0, 0); else mclass = input; if (mclass) { extern msg_hclass_t * const sip_extensions[]; int i; for (i = 0; sip_extensions[i]; i++) { msg_hclass_t *hclass = sip_extensions[i]; if (mclass->mc_unknown != msg_find_hclass(mclass, hclass->hc_name, NULL)) continue; if (msg_mclass_insert_header(mclass, hclass, 0) < 0) { if (input != mclass) free(mclass); return mclass = NULL; } } } return mclass;}/** Extract the SIP message body, including separator line. * * @param msg message object [IN] * @param sip public SIP message structure [IN/OUT] * @param b buffer containing unparsed data [IN] * @param bsiz buffer size [IN] * @param eos true if buffer contains whole message [IN] * * @retval -1 error * @retval 0 cannot proceed * @retval m */issize_t sip_extract_body(msg_t *msg, sip_t *sip, char b[], isize_t bsiz, int eos){ ssize_t m = 0; size_t body_len; if (!(sip->sip_flags & MSG_FLG_BODY)) { /* We are looking at a potential empty line */ m = msg_extract_separator(msg, (msg_pub_t *)sip, b, bsiz, eos); if (m <= 0) return m; sip->sip_flags |= MSG_FLG_BODY; b += m; bsiz -= m; } if (sip->sip_content_length) body_len = sip->sip_content_length->l_length; else if (MSG_IS_MAILBOX(sip->sip_flags)) /* message fragments */ body_len = 0; else if (eos) body_len = bsiz; else if (bsiz == 0) return m; else return -1; if (body_len == 0) { sip->sip_flags |= MSG_FLG_COMPLETE; return m; } if (m) return m; if (eos && body_len > bsiz) { sip->sip_flags |= MSG_FLG_TRUNC | MSG_FLG_ERROR; return bsiz; } if ((m = msg_extract_payload(msg, (msg_pub_t *)sip, NULL, body_len, b, bsiz, eos)) == -1) return -1; sip->sip_flags |= MSG_FLG_FRAGS; if (bsiz >= body_len) sip->sip_flags |= MSG_FLG_COMPLETE; return m;}/** Parse SIP version. * * Parse a SIP version string. Update the * pointer at @a ss to first non-LWS character after the version string. * * @param ss string to be parsed [IN/OUT] * @param ver value result for version [OUT] * * @retval 0 when successful, * @retval -1 upon an error. */int sip_version_d(char **ss, char const **ver){ char *s = *ss; char const *result; size_t const version_size = sizeof(sip_version_2_0) - 1; if (strncasecmp(s, sip_version_2_0, version_size) == 0 && !IS_TOKEN(s[version_size])) { result = sip_version_2_0; s += version_size; } else { /* Version consists of two tokens, separated by / */ size_t l1 = 0, l2 = 0, n; result = s; l1 = span_token(s); for (n = l1; IS_LWS(s[n]); n++); if (s[n] == '/') { for (n++; IS_LWS(s[n]); n++); l2 = span_token(s + n); n += l2; } if (l1 == 0 || l2 == 0) return -1; /* If there is extra ws between tokens, compact version */ if (n > l1 + 1 + l2) { s[l1] = '/'; memmove(s + l1 + 1, s + n - l2, l2); s[l1 + 1 + l2] = 0; /* Compare again with compacted version */ if (strcasecmp(s, sip_version_2_0) == 0) result = sip_version_2_0; } s += n; } while (IS_WS(*s)) *s++ = '\0'; *ss = s; if (ver) *ver = result; return 0;}/** Calculate extra space required by version string */isize_t sip_version_xtra(char const *version){ if (version == SIP_VERSION_CURRENT) return 0; return MSG_STRING_SIZE(version);}/** Duplicate a transport string */void sip_version_dup(char **pp, char const **dd, char const *s){ if (s == SIP_VERSION_CURRENT) *dd = s; else MSG_STRING_DUP(*pp, *dd, s);}char const sip_method_name_invite[] = "INVITE";char const sip_method_name_ack[] = "ACK";char const sip_method_name_cancel[] = "CANCEL";char const sip_method_name_bye[] = "BYE";char const sip_method_name_options[] = "OPTIONS";char const sip_method_name_register[] = "REGISTER";char const sip_method_name_info[] = "INFO";char const sip_method_name_prack[] = "PRACK";char const sip_method_name_update[] = "UPDATE";char const sip_method_name_message[] = "MESSAGE";char const sip_method_name_subscribe[] = "SUBSCRIBE";char const sip_method_name_notify[] = "NOTIFY";char const sip_method_name_refer[] = "REFER";char const sip_method_name_publish[] = "PUBLISH";/** Well-known SIP method names. */char const * const sip_method_names[] = { "<UNKNOWN>", sip_method_name_invite, sip_method_name_ack, sip_method_name_cancel, sip_method_name_bye, sip_method_name_options, sip_method_name_register, sip_method_name_info, sip_method_name_prack, sip_method_name_update, sip_method_name_message, sip_method_name_subscribe, sip_method_name_notify, sip_method_name_refer,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -