📄 sip_basic.c
字号:
else { memset(b, 0, len + 1); } h->sh_data = pl->pl_data = b; h->sh_len = pl->pl_len = len; } return pl;}/* ====================================================================== *//**@SIP_HEADER sip_separator Separator Line * * An empty line separates message headers from the message body (payload). * In order to avoid modifying messages with integrity protection, the * separator line has its own header structure which is included in the * #sip_t structure. * * The parsed separator line is stored in #sip_separator_t structure. *//**@ingroup sip_separator * @typedef typedef struct sip_separator_s sip_separator_t; * * The structure #sip_separator_t contains representation of separator line * between message headers and body. * * The #sip_separator_t is defined as follows: * @code * typedef struct sip_separator_s { * msg_common_t sep_common[1]; // Common fragment info * msg_header_t *sep_next; // Pointer to next header * char sep_data[4]; // NUL-terminated separator * } sip_separator_t; * @endcode */#define sip_separator_d msg_separator_d#define sip_separator_e msg_separator_e#define sip_separator_insert msg_separator_insertmsg_hclass_t sip_separator_class[] = SIP_HEADER_CLASS(separator, NULL, "", sep_common, single, any);/**@ingroup sip_separator * * Create a @ref sip_separator "SIP separator line" structure. */sip_separator_t *sip_separator_create(su_home_t *home){ sip_separator_t *sep = (sip_separator_t *) sip_header_alloc(home, sip_separator_class, 0); if (sep) strcpy(sep->sep_data, CRLF); return sep;}/* ====================================================================== *//**@SIP_HEADER sip_unknown Unknown Headers * * The unknown headers are handled with #sip_unknown_t structure. The * unknown header name is stored in @a un_name field and the header field * following the colon is stored in @a un_value field. * * @note It is possible to speed up parsing process by creating a parser * which does understand only a minimum number of headers. If such a parser * is used, some well-known headers are regarded as unknown and put into * list of unknown headers. *//**@ingroup sip_unknown * @typedef typedef struct sip_unknown_s sip_unknown_t; * * The structure #sip_unknown_t contains representation of unknown headers. * * The #sip_unknown_t is defined as follows: * @code * typedef struct msg_unknown_s { * msg_common_t un_common[1]; // Common fragment info * msg_unknown_t *un_next; // Link to next unknown header * char const *un_name; // Header name * char const *un_value; // Header field value * } sip_unknown_t; * @endcode */#define sip_unknown_dup_xtra msg_unknown_dup_xtra #define sip_unknown_dup_one msg_unknown_dup_one#define sip_unknown_update NULLmsg_hclass_t sip_unknown_class[] = SIP_HEADER_CLASS(unknown, "", "", un_common, append, unknown);issize_t sip_unknown_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ return msg_unknown_d(home, h, s, slen);}issize_t sip_unknown_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){ return msg_unknown_e(b, bsiz, h, flags);}/* ====================================================================== *//**@SIP_HEADER sip_error Erroneous Headers * * The erroneous headers are stored in #sip_error_t structure. * * @note Other headers (like duplicate @ContentLength headers) may be put * into the list of erroneous headers (@c sip->sip_error). If the list of * erroneous headers is processed, the header type must be validated first * by calling sip_is_error() (or by other relevant tests). *//**@ingroup sip_error * @typedef typedef msg_error_t sip_error_t; * The structure #sip_error_t contains representation of error headers. * * The #sip_error_t is defined as follows: * @code * typedef struct msg_error_s { * msg_common_t er_common[1]; // Common fragment info * msg_error_t *er_next; // Link to next header * char const *er_name; // Name of bad header (if any) * } sip_error_t; * @endcode */msg_hclass_t sip_error_class[] =SIP_HEADER_CLASS(error, NULL, "", er_common, append, any);issize_t sip_error_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen){ return 0;}issize_t sip_error_e(char b[], isize_t bsiz, msg_header_t const *h, int flags){ /* There is no way to encode an erroneous header */ return 0;}/* ====================================================================== *//* * addr = ("To" | "t" | "From" | "f") ":" * ( name-addr | addr-spec ) *( ";" addr-params ) * name-addr = [ display-name ] "<" addr-spec ">" * addr-spec = SIP-URL | URI * display-name = *token | quoted-string *//**Parse @e name-addr. * * Parses <i>( name-addr | addr-spec )</i> construct on @Contact, @From, * @To, and other compatible headers. It splits the argument string in * four parts: * * @par * @e [display-name] @e addr-spec @e [parameters] @e [comment] @e [ss] * * @param home pointer to memory home * @param inout_s pointer to pointer to string to be parsed * @param return_display value-result parameter for @e display-name * @param return_url value-result parameter for @e addr-spec * @param return_params value-result paramater for @e parameters * @param return_comment value-result parameter for @e comment * * @note After succesful call to the function @c sip_name_addr_d(), *ss * contains pointer to the first character not beloging to @e name-addr, * most probably a comma. If that character is a separator, the last parameter * may not be NUL (zero) terminated. So, after examining value of @a **ss, * the calling function @b MUST set it to NUL. * * @retval 0 if successful * @retval -1 upon an error * * @sa @From, @To, @Contact */issize_t sip_name_addr_d(su_home_t *home, char **inout_s, char const **return_display, url_t *return_url, msg_param_t const **return_params, char const **return_comment){ char c, *s = *inout_s; char *display = NULL, *addr_spec = NULL; size_t n; if (*s == '\0') /* Empty string */ return -1; if (return_display && *s == '"') { /* Quoted string */ if (msg_quoted_d(&s, &display) == -1) return -1; /* Now, we should have a '<' in s[0] */ if (s[0] != '<') return -1; s++[0] = '\0'; /* NUL terminate quoted string... */ n = strcspn(s, ">"); addr_spec = s; s += n; if (*s) *s++ = '\0'; else return -1; } else { if (return_display) n = span_token_lws(s); else n = 0; if (s[n] == '<') { /* OK, we got a display name */ display = s; s += n + 1; /* NUL terminate display name */ while (n > 0 && IS_LWS(display[n - 1])) n--; if (n > 0) display[n] = '\0'; else display = ""; n = strcspn(s, ">"); addr_spec = s; s += n; if (*s) *s++ = '\0'; else return -1; } else { /* addr-spec only */ addr_spec = s; /**@sa * Discussion about comma, semicolon and question mark in * @RFC3261 section 20.10. */ if (return_params) n = strcspn(s, " \t,;?"); /* DO NOT accept ,;? in URL */ else /* P-Asserted-Identity and friends */ n = strcspn(s, " ,"); /* DO NOT accept , in URL */ s += n; if (IS_LWS(*s)) *s++ = '\0'; } } skip_lws(&s); if (return_display) *return_display = display; /* Now, url may still not be NUL terminated, e.g., if * it is like "Contact: url:foo,sip:bar,sip:zunk" */ c = *s; *s = '\0'; /* terminate temporarily */ /* Do not accept an empty URL */ if (addr_spec[0] == '\0') return -1; if (url_d(return_url, addr_spec) == -1) return -1; *s = c; /* return terminator */ *inout_s = s; if (c == ';' && return_params) if (msg_params_d(home, inout_s, return_params) == -1) return -1; if (**inout_s == '(' && return_comment) if (msg_comment_d(inout_s, return_comment) == -1) return -1; return 0;}/**Encode @e name-addr and parameter list. * * Encodes @e name-addr headers, like @From, @To, @CallInfo, @ErrorInfo, * @Route, and @RecordRoute. * * @param b buffer to store the encoding result * @param bsiz size of the buffer @a b * @param flags encoding flags * @param display display name encoded before the @a url (may be NULL) * @param brackets if true, use always brackets around @a url * @param url pointer to URL structure * @param params pointer to parameter list (may be NULL) * @param comment comment string encoded after others (may be NULL) * * @return * Returns number of characters in encoding, excluding the * final NUL. * * @note * The encoding result may be incomplete if the buffer size is not large * enough to store the whole encoding result. */issize_t sip_name_addr_e(char b[], isize_t bsiz, int flags, char const *display, int brackets, url_t const url[], msg_param_t const params[], char const *comment){ int const compact = MSG_IS_COMPACT(flags); char const *u; char *b0 = b, *end = b + bsiz; brackets = brackets || display || (url && (url->url_params || url->url_headers || ((u = url->url_user) && u[strcspn(u, ";,?")]) || ((u = url->url_password) && u[strcspn(u, ",")]))); if (display && display[0]) { MSG_STRING_E(b, end, display); if (!compact) MSG_CHAR_E(b, end, ' '); } if (url) { if (brackets) MSG_CHAR_E(b, end, '<'); URL_E(b, end, url); if (brackets) MSG_CHAR_E(b, end, '>'); } MSG_PARAMS_E(b, end, params, flags); if (comment) { if (!compact) MSG_CHAR_E(b, end, ' '); MSG_CHAR_E(b, end, '('); MSG_STRING_E(b, end, comment); MSG_CHAR_E(b, end, ')'); } MSG_TERM_E(b, end); return b - b0;}/** Calculate the extra size needed to duplicate a name-addr-params construct. * * @param display display name (may be NULL) * @param addr pointer to URL structure * @param params pointer to parameter list (may be NULL) * @param offset base offset * * @retval Size of duplicated name-addr-params construct, including base offset. * * @NEW_1_12_7. */isize_t sip_name_addr_xtra(char const *display, url_t const *addr, msg_param_t const params[], isize_t offset){ SIP_PARAMS_SIZE(offset, params); offset += SIP_STRING_SIZE(display); offset += url_xtra(addr); return offset;}/**Duplicate a name-addr-params construct. * * @param d_display value-result parameter for copied @e name (may be NULL) * @param display display name (may be NULL) * @param d_addr value-result parameter for copied @e address * @param addr pointer to URL address structure * @param d_params value-result parameter for copied parameters (may be NULL) * @param params pointer to parameter list (may be NULL) * @param b pointer to memory pool * @param xtra size of the memory pool * * @retval End of the memory area used. * * @NEW_1_12_7. */char *sip_name_addr_dup(char const **d_display, char const *display, url_t *d_addr, url_t const *addr, msg_param_t const **d_params, msg_param_t const params[], char *b, isize_t xtra){ char *end = b + xtra; if (d_params) b = msg_params_dup(d_params, params, b, xtra); URL_DUP(b, end, d_addr, addr); if (d_display) MSG_STRING_DUP(b, *d_display, display); assert(b <= end); return b;}/** Parse @To or @From headers */static issize_t sip_addr_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ sip_addr_t *a = (sip_addr_t *)h; char const *comment = NULL; if (sip_name_addr_d(home, &s, &a->a_display, a->a_url, &a->a_params, &comment) == -1 || *s /* XXX - something extra? */) return -1; a->a_tag = msg_params_find(a->a_params, "tag="); return 0;}static int sip_addr_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){ sip_addr_t const *a = (sip_addr_t const *)h; return sip_name_addr_e(b, bsiz, flags, a->a_display, MSG_IS_CANONIC(flags), a->a_url, a->a_params, NULL);}/** * Extra dup size of a sip_addr_t object. * * This function calculates extra size required when duplicating a * sip_addr_t object. * * @param a pointer to a sip_addr_t object * * @return * Size of strings related to sip_addr_t object. */staticisize_t sip_addr_dup_xtra(sip_header_t const *h, isize_t offset){ sip_addr_t const *a = (sip_addr_t const *)h; return sip_name_addr_xtra(a->a_display, a->a_url, a->a_params, offset);}/**@internal * Duplicate one sip_addr_t object. */static char *sip_addr_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra){ sip_addr_t *a = (sip_addr_t *)dst; sip_addr_t const *o = (sip_addr_t *)src;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -