📄 sip_basic.c
字号:
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. *//**@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 SIP separator line structure. */sip_separator_t *sip_separator_create(su_home_t *home){ sip_separator_t *sep = sip_header_alloc(home, sip_separator_class, 0)->sh_separator; 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 whole * unknown header including its name is included in the header value string * @a g_value. * * @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. */#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);int sip_unknown_d(su_home_t *home, sip_header_t *h, char *s, int slen){ return msg_unknown_d(home, h, s, slen);}int sip_unknown_e(char b[], int 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 @b Content-Length 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; * Type for erroneous headers. */msg_hclass_t sip_error_class[] =SIP_HEADER_CLASS(error, NULL, "", er_common, append, any);int sip_error_d(su_home_t *home, msg_header_t *h, char *s, int slen){ return 0;}int sip_error_e(char b[], int 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 @b Contact, @b From, * @b 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 comma. If that character is a separator, the last parameter * may not be NUL (zero) terminated. So, after examining value of @a **ss, * tohe calling function @b MUST set it to NUL. * * @note * Other header like @b Route or @b Route-Record may require some tweaking. * * @return * The function @c sip_name_addr_d() returns 0 if successful, and -1 upon an * error. */int 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; int n; 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, " ,;?"); /* 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 */ 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, Call-Info, Error-Info, * Route, and Record-Route. * * @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. */int sip_name_addr_e(char b[], int 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;}/** Parse To or From headers */int sip_addr_d(su_home_t *home, sip_header_t *h, char *s, int 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[], int 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. */staticint sip_addr_dup_xtra(sip_header_t const *h, int offset){ int rv = offset; sip_addr_t const *a = (sip_addr_t const *)h; MSG_PARAMS_SIZE(rv, a->a_params); rv += MSG_STRING_SIZE(a->a_display); rv += url_xtra(a->a_url); return rv;}/**@internal * Duplicate one sip_addr_t object. */static char *sip_addr_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, int xtra){ sip_addr_t *a = (sip_addr_t *)dst; sip_addr_t const *o = (sip_addr_t *)src; char *end = b + xtra; b = msg_params_dup(&a->a_params, o->a_params, b, xtra); MSG_STRING_DUP(b, a->a_display, o->a_display); URL_DUP(b, end, a->a_url, o->a_url); assert(b <= end); return b;}/** Update parameters in sip_addr_t object */static int sip_addr_update(msg_common_t *h, char const *name, int namelen, char const *value){ sip_addr_t *a = (sip_addr_t *)h; if (name == NULL) { a->a_tag = NULL; } else if (namelen == strlen("tag") && !strncasecmp(name, "tag", namelen)) { a->a_tag = value; } return 0;}/** Create an address header object from URL */static sip_addr_t *sip_addr_make_url(su_home_t *home, msg_hclass_t *hc, url_string_t const *us){ int n; sip_header_t *h; n = url_xtra(us->us_url); h = sip_header_alloc(home, sip_to_class, n); if (h) { sip_addr_t *a = h->sh_to; char *s2 = sip_header_data(h); if (url_dup(s2, n, a->a_url, us->us_url) == n) return a; su_free(home, h); } return NULL;}/** Add a tag to address structure. */staticint sip_addr_tag(su_home_t *home, sip_addr_t *a, char const *tag){ if (a && tag) { msg_param_t value = strchr(tag, '='); if (value) value = strchr(value, '=') + 1; else value = tag; if (a->a_tag) { if (strcasecmp(a->a_tag, value) == 0) return 0; else return -1; } if (tag == value) tag = su_sprintf(home, "tag=%s", tag); else tag = su_strdup(home, tag); if (tag) if (msg_header_replace_param(home, a->a_common, tag) >= 0) return 0; } return -1;}/* ====================================================================== *//**@SIP_HEADER sip_call_id Call-ID Header * * The @b Call-ID header uniquely identifies a particular invitation or all * registrations of a particular client. It is defined in [S10.12] as * follows: * * @code * Call-ID = ( "Call-ID" / "i" ) HCOLON callid * callid = word [ "@" word ] * word = 1*(alphanum / "-" / "." / "!" / "%" / "*" / * "_" / "+" / "`" / "'" / "~" / "(" / ")" / "<" / ">" / * ":" / "\" / DQUOTE / "/" / "[" / "]" / "?" / "{" / "}" ) * @endcode * *//**@ingroup sip_call_id * @typedef typedef struct sip_call_id_s sip_call_id_t; * * The structure #sip_call_id_t contains representation of SIP @b Call-ID * header. * * The #sip_call_id_t is defined as follows:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -