📄 sip_basic.c
字号:
* @retval -1 upon an error. */int sip_from_tag(su_home_t *home, sip_from_t *from, char const *tag){ return sip_addr_tag(home, from, tag);}int sip_to_tag(su_home_t *home, sip_to_t *to, char const *tag){ return sip_addr_tag(home, to, tag);}/* ====================================================================== *//**@SIP_HEADER sip_max_forwards Max-Forwards Header * * The Max-Forwards header is used to limit the number of proxies or * gateways that can forward the request. The Max-Forwards syntax is * defined in @RFC3261 as follows: * * @code * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT * @endcode * * * The parsed Max-Forwards header is stored in #sip_max_forwards_t structure. *//**@ingroup sip_max_forwards * @typedef typedef struct sip_max_forwards_s sip_max_forwards_t; * * The structure #sip_max_forwards_t contains representation of SIP * @MaxForwards header. * * The #sip_max_forwards_t is defined as follows: * @code * typedef struct sip_max_forwards_s { * sip_common_t mf_common[1]; // Common fragment info * sip_error_t *mf_next; // Link to next (dummy) * unsigned long mf_count; // Digits * } sip_max_forwards_t; * @endcode */msg_hclass_t sip_max_forwards_class[] = SIP_HEADER_CLASS(max_forwards, "Max-Forwards", "", mf_common, single, any);issize_t sip_max_forwards_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ return sip_numeric_d(home, h, s, slen);}issize_t sip_max_forwards_e(char b[], isize_t bsiz, sip_header_t const *h, int f){ assert(sip_is_max_forwards(h)); return sip_numeric_e(b, bsiz, h, f);}/* ====================================================================== *//**@SIP_HEADER sip_min_expires Min-Expires Header * * The Min-Expires header is used to limit the number of proxies or * gateways that can forward the request. The Min-Expires syntax is * defined in @RFC3261 as follows: * * @code * Min-Expires = "Min-Expires" HCOLON delta-seconds * @endcode * * The parsed Min-Expires header is stored in #sip_min_expires_t structure. *//**@ingroup sip_min_expires * @typedef typedef struct sip_min_expires_s sip_min_expires_t; * * The structure #sip_min_expires_t contains representation of SIP * @MinExpires header. * * The #sip_min_expires_t is defined as follows: * @code * typedef struct sip_min_expires_s { * sip_common_t me_common[1]; // Common fragment info * sip_error_t *me_next; // Link to next (dummy) * unsigned long me_delta; // Seconds * } sip_min_expires_t; * @endcode */msg_hclass_t sip_min_expires_class[] = SIP_HEADER_CLASS(min_expires, "Min-Expires", "", me_common, single, any);issize_t sip_min_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ return sip_numeric_d(home, h, s, slen);}issize_t sip_min_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int f){ assert(sip_is_min_expires(h)); return sip_numeric_e(b, bsiz, h, f);}/* ====================================================================== *//**@SIP_HEADER sip_retry_after Retry-After Header * * The Retry-After response-header field @RFC3261 section 20.33 can be used to * indicate how long the service is expected to be unavailable or when the * called party anticipates being available again. Its syntax is defined in * @RFC3261 as follows: * * @code * Retry-After = "Retry-After" HCOLON delta-seconds * [ comment ] *( SEMI retry-param ) * retry-param = ("duration" EQUAL delta-seconds) * / generic-param * @endcode * * The parsed Retry-After header is stored in #sip_retry_after_t structure. *//**@ingroup sip_retry_after * @typedef struct sip_retry_after_s sip_retry_after_t; * * The structure #sip_retry_after_t contains representation of an * @RetryAfter header. * * The #sip_retry_after_t is defined as follows: * @code * typedef struct sip_retry_after_s { * sip_common_t af_common[1]; // Common fragment info * sip_error_t *af_next; // Link to next (dummy) * sip_time_t af_delta; // Seconds to before retry * char const *af_comment; // Comment string * msg_param_t const *af_params; // List of parameters * char const *af_duration; // Duration parameter * } sip_retry_after_t; * @endcode */static msg_xtra_f sip_retry_after_dup_xtra;static msg_dup_f sip_retry_after_dup_one;static msg_update_f sip_retry_after_update;msg_hclass_t sip_retry_after_class[] = SIP_HEADER_CLASS(retry_after, "Retry-After", "", af_params, single, retry_after);issize_t sip_retry_after_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ sip_retry_after_t *af = (sip_retry_after_t *)h; if ((msg_delta_d((char const **)&s, &af->af_delta) < 0) || (*s == '(' && msg_comment_d(&s, &af->af_comment) == -1) || (*s == ';' && msg_params_d(home, &s, &af->af_params) == -1) || (*s != '\0')) { if (af->af_params) su_free(home, (void *)af->af_params), af->af_params = NULL; return -1; } if (af->af_params) msg_header_update_params(h->sh_common, 0); return 0;}issize_t sip_retry_after_e(char b[], isize_t bsiz, sip_header_t const *h, int f){ sip_retry_after_t const *af = (sip_retry_after_t *)h; int const compact = MSG_IS_COMPACT(f); char *b0 = b, *end = b + bsiz; b += snprintf(b, bsiz, "%lu", af->af_delta); if (af->af_comment) { if (!compact) MSG_CHAR_E(b, end, ' '); MSG_CHAR_E(b, end, '('); MSG_STRING_E(b, end, af->af_comment); MSG_CHAR_E(b, end, ')'); if (!compact && af->af_params && af->af_params[0]) MSG_CHAR_E(b, end, ' '); } if (af->af_params) MSG_PARAMS_E(b, end, af->af_params, f); MSG_TERM_E(b, end); return b - b0;}isize_t sip_retry_after_dup_xtra(sip_header_t const *h, isize_t offset){ sip_retry_after_t const *af = (sip_retry_after_t *)h; MSG_PARAMS_SIZE(offset, af->af_params); offset += MSG_STRING_SIZE(af->af_comment); return offset;}char *sip_retry_after_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra){ sip_retry_after_t *af = (sip_retry_after_t *)dst; sip_retry_after_t const *o = (sip_retry_after_t *)src; char *end = b + xtra; b = msg_params_dup(&af->af_params, o->af_params, b, xtra); MSG_STRING_DUP(b, af->af_comment, o->af_comment); af->af_delta = o->af_delta; assert(b <= end); (void)end; return b;}static int sip_retry_after_update(msg_common_t *h, char const *name, isize_t namelen, char const *value){ sip_retry_after_t *af = (sip_retry_after_t *)h; if (name == NULL) { af->af_duration = NULL; } else if (namelen == strlen("duration") && !strncasecmp(name, "duration", namelen)) { af->af_duration = value; } return 0;}/* ====================================================================== *//**Parse a @Route or a @RecordRoute header. * * @retval 0 when successful, * @retval -1 upon an error. */issize_t sip_any_route_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ sip_route_t *r = (sip_route_t *)h; assert(h); while (*s == ',') /* Ignore empty entries (comma-whitespace) */ *s = '\0', s += span_lws(s + 1) + 1; if (sip_name_addr_d(home, &s, &r->r_display, r->r_url, &r->r_params, NULL) < 0) return -1; return msg_parse_next_field(home, h, s, slen);}issize_t sip_any_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){ sip_route_t const *r = (sip_route_t *)h; return sip_name_addr_e(b, bsiz, flags, r->r_display, 1, r->r_url, r->r_params, NULL);}isize_t sip_any_route_dup_xtra(sip_header_t const *h, isize_t offset){ sip_route_t const *r = (sip_route_t *)h; return sip_name_addr_xtra(r->r_display, r->r_url, r->r_params, offset);}char *sip_any_route_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra){ sip_route_t *r = (sip_route_t *)dst; sip_route_t const *o = (sip_route_t *)src; return sip_name_addr_dup(&r->r_display, o->r_display, r->r_url, o->r_url, &r->r_params, o->r_params, b, xtra);}#define sip_any_route_update NULL/** Create a route. * * Create a route or record-route entry * from two URLs; first one provides the URL, second maddr parameter and * port. * * @param home memory home * @param rq_url route URL * @param maddr optional route address and port * */staticsip_route_t *sip_any_route_create(su_home_t *home, msg_hclass_t *hc, url_t const *rq_url, url_t const *maddr){ sip_header_t *h; sip_route_t *rr; url_t url[1]; size_t xtra, n, n_url, n_params, n_addr; char *b, *param; *url = *rq_url; if (maddr) { url->url_port = maddr->url_port; url->url_params = NULL; } n_url = url_xtra(url); n_params = maddr && maddr->url_params ? strlen(maddr->url_params) : 0; if (maddr && (!maddr->url_params || !url_param(maddr->url_params, "maddr", NULL, 0))) n_addr = (n_params != 0) + strlen("maddr=") + strlen(maddr->url_host); else n_addr = 0; xtra = n_url + n_params + n_addr + (n_params || n_addr); h = sip_header_alloc(home, hc, xtra); if ((rr = (sip_record_route_t *)h)) { b = sip_header_data(h); n = url_dup(b, n_url, rr->r_url, url); assert(n == n_url); if (n_params || n_addr) { param = b + n_url; if (n_params) { rr->r_url->url_params = strcpy(param, maddr->url_params); param += n_params; } if (n_addr) { if (n_params) *param++ = ';'; strcpy(param, "maddr="), param += strlen("maddr="); strcpy(param, maddr->url_host), param += strlen(maddr->url_host); } assert(b + xtra == param + 1); } } return rr;}/* ====================================================================== *//**@SIP_HEADER sip_route Route Header * * The Route headers is used to store the route set of a transaction. * The Route header is defined in @RFC3261 as follows: * * @code * Route = "Route" HCOLON route-param *(COMMA route-param) * route-param = name-addr *( SEMI rr-param ) * @endcode * * The parsed Route header is stored in #sip_route_t structure. *//**@ingroup sip_route * @typedef typedef struct sip_route_s sip_route_t; * * The structure #sip_route_t contains representation of SIP @Route header. * * The #sip_route_t is defined as follows: * @code * typedef struct sip_route_s { * sip_common_t r_common[1]; // Common fragment info * sip_route_t *r_next; // Link to next @Route * char const *r_display; // Display name * url_t r_url[1]; // @Route URL * msg_param_t const *r_params; // List of route parameters * } sip_route_t; * @endcode */msg_hclass_t sip_route_class[] = SIP_HEADER_CLASS(route, "Route", "", r_params, append, any_route);issize_t sip_route_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ return sip_any_route_d(home, h, s, slen);}issize_t sip_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){ assert(sip_is_route(h)); return sip_any_route_e(b, bsiz, h, flags);}/**@ingroup sip_route * @brief Create a @Route header object. * * Creates a route entry from two URLs; first one provides the URL, second * maddr parameter and port. * * @param home memory home * @param url route URL * @param maddr optional route address and port * * @return * Returns a pointer to newly created @Route header object when successful, * or NULL upon an error. */sip_route_t *sip_route_create(su_home_t *home, url_t const *url, url_t const *maddr){ return sip_any_route_create(home, sip_route_class, url, maddr); }/* ====================================================================== *//**@SIP_HEADER sip_record_route Record-Route Header * * The Record-Route headers are used to establish a route for transactions * belonging to a session. The Record-Route header is defined in @RFC3261 * as follows: * * @code * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route) * rec-route = name-addr *( SEMI rr-param ) * rr-param = generic-param * @endcode * * The parsed Record-Route header is stored in #sip_record_route_t structure. *//**@ingroup sip_record_route * @typedef typedef struct sip_record_route_s sip_record_route_t; * * The structure #sip_record_route_t contains representation of SIP * @RecordRoute header. * * The #sip_record_route_t is defined as follows: * @code * typedef struct sip_route_s { * sip_common_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -