📄 sip_basic.c
字号:
return sip_name_addr_dup(&a->a_display, o->a_display, a->a_url, o->a_url, &a->a_params, o->a_params, b, xtra);}/** Update parameters in sip_addr_t object */static int sip_addr_update(msg_common_t *h, char const *name, isize_t 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){ size_t n; sip_header_t *h; n = url_xtra(us->us_url); h = sip_header_alloc(home, hc, n); if (h) { sip_addr_t *a = (sip_to_t *)h; char *s2 = sip_header_data(h); if ((size_t)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 @RFC3261 as * follows: * * @code * Call-ID = ( "Call-ID" / "i" ) HCOLON callid * callid = word [ "@" word ] * word = 1*(alphanum / "-" / "." / "!" / "%" / "*" / * "_" / "+" / "`" / "'" / "~" / "(" / ")" / "<" / ">" / * ":" / "\" / DQUOTE / "/" / "[" / "]" / "?" / "{" / "}" ) * @endcode * * The parsed Call-ID Header is stored in #sip_call_id_t structure. *//**@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 @CallID * header. * * The #sip_call_id_t is defined as follows: * @code * typedef struct sip_call_id_s { * sip_common_t i_common[1]; // Common fragment info * sip_call_id_t *i_next; // Link to next (dummy) * char const *i_id; // ID value * uint32_t i_hash; // Hash value (always nonzero) * } sip_call_id_t; * @endcode */static msg_xtra_f sip_call_id_dup_xtra;static msg_dup_f sip_call_id_dup_one;#define sip_call_id_update NULLmsg_hclass_t sip_call_id_class[] = SIP_HEADER_CLASS(call_id, "Call-ID", "i", i_common, single, call_id);issize_t sip_call_id_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ sip_call_id_t *i = (sip_call_id_t *)h; i->i_id = s; /* XXX - why not sip_word_at_word_d(&s); */ i->i_hash = msg_hash_string(s); return 0;}issize_t sip_call_id_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){ sip_call_id_t const *i = (sip_call_id_t *)h; size_t n = strlen(i->i_id); if (bsiz > n) strcpy(b, i->i_id); return (issize_t)n;}/** Extra size of a #sip_call_id_t object. */isize_t sip_call_id_dup_xtra(sip_header_t const *h, isize_t offset){ sip_call_id_t const *i = (sip_call_id_t *)h; return offset + MSG_STRING_SIZE(i->i_id);}/**Duplicate a sip_call_id object. * * Duplicate (copy deeply) a single #sip_call_id_t header object. * * @param dst pointer to newly allocated header object * @param src pointer to a header object to be duplicated * @param b memory buffer used to copy external references * @param xtra number bytes in buffer @a b * * @return Pointer to the new copy of #sip_call_id_t object, or @c NULL * upon an error. */char *sip_call_id_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra){ sip_call_id_t *i = (sip_call_id_t *)dst; sip_call_id_t const *o = (sip_call_id_t *)src; char *end = b + xtra; MSG_STRING_DUP(b, i->i_id, o->i_id); if (!(i->i_hash = o->i_hash)) i->i_hash = msg_hash_string(i->i_id); assert(b <= end); (void)end; return b;}/**@ingroup sip_call_id * * Create a @CallID header object. * * Create a Call-ID header object with a new unique value. It uses * su_guid_generate() function to generate the value. If the local host name * @a domain is specified, it is prepended to the generated value instead of * local MAC address. * @param home memory home * @param domain local domain name * * @return A pointer to newly created @CallID header object when * successful or NULL upon an error. * * @sa su_guid_generate(), su_guid_sprintf() */sip_call_id_t *sip_call_id_create(su_home_t *home, char const *domain){ sip_call_id_t *i; size_t xtra = su_guid_strlen + 1 + (domain ? strlen(domain) + 1 : 0); i = (sip_call_id_t *)sip_header_alloc(home, sip_call_id_class, xtra); if (i) { char *b; su_guid_t guid[1]; i->i_id = b = (char *)(i + 1); su_guid_generate(guid); /* * Guid looks like "NNNNNNNN-NNNN-NNNN-NNNN-XXXXXXXXXXXX" * where NNNNNNNN-NNNN-NNNN-NNNN is timestamp and XX is MAC address * (but we use usually random ID for MAC because we do not have * guid generator available for all processes within node) */ su_guid_sprintf(b, su_guid_strlen + 1, guid); /* If we have a domain name don't include MAC address at the end of guid */ if (domain) { b[8 + 5 + 5 + 5] = '@'; strcpy(b + 8 + 5 + 5 + 5 + 1, domain); } i->i_hash = msg_hash_string(i->i_id); } return i;}/* ====================================================================== *//**@SIP_HEADER sip_cseq CSeq Header * * The CSeq header (command sequence) uniquely identifies transactions * within a dialog. It is defined in @RFC3261 as follows: * * @code * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method * Method = INVITEm / ACKm / OPTIONSm / BYEm * / CANCELm / REGISTERm * / extension-method * extension-method = token * @endcode * * The parsed CSeq header is stored in #sip_cseq_t structure. *//**@ingroup sip_cseq * @typedef typedef struct sip_cseq_s sip_cseq_t; * * The structure #sip_cseq_t contains representation of SIP @CSeq header. * * The #sip_cseq_t is defined as follows: * @code * typedef struct sip_cseq_s { * sip_common_t cs_common[1]; // Common fragment info * sip_error_t *cs_next; // Link to next (dummy) * uint32_t cs_seq; // Sequence number * sip_method_t cs_method; // Method enum * char const *cs_method_name; // Method name * } sip_cseq_t; * @endcode */static msg_xtra_f sip_cseq_dup_xtra;static msg_dup_f sip_cseq_dup_one;#define sip_cseq_update NULLmsg_hclass_t sip_cseq_class[] = SIP_HEADER_CLASS(cseq, "CSeq", "", cs_common, single, cseq);issize_t sip_cseq_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){ sip_cseq_t *cs = (sip_cseq_t *)h; if (msg_uint32_d(&s, &cs->cs_seq) < 0) return -1; if (*s) { if ((cs->cs_method = sip_method_d(&s, &cs->cs_method_name)) >= 0) return 0; } return -1;}issize_t sip_cseq_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){ sip_cseq_t const *cs = (sip_cseq_t *)h; assert(sip_is_cseq(h)); return snprintf(b, bsiz, "%u %s", cs->cs_seq, cs->cs_method_name);}isize_t sip_cseq_dup_xtra(sip_header_t const *h, isize_t offset){ sip_cseq_t const *cs = (sip_cseq_t *)h; if (!cs->cs_method) return offset + MSG_STRING_SIZE(cs->cs_method_name); else return offset;}char *sip_cseq_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, isize_t xtra){ sip_cseq_t *cs = (sip_cseq_t *)dst; sip_cseq_t const *o = (sip_cseq_t *)src; char *end = b + xtra; if (!(cs->cs_method = o->cs_method)) MSG_STRING_DUP(b, cs->cs_method_name, o->cs_method_name); else cs->cs_method_name = o->cs_method_name; cs->cs_seq = o->cs_seq; assert(b <= end); (void)end; return b;}/**@ingroup sip_cseq * *燙reate a @CSeq header object. * * Create a @CSeq header object with the * sequence number @a seq, method enum @a method and method name @a * method_name. The memory for the header object is allocated from the * memory home @a home. * * @param home memory home * @param seq sequence number * @param method method enum * @param method_name method name (required if method is not well-known) * * @par Example * The following code fragment creates a cseq object for OPTIONS request: * @code * sip_cseq_t *cseq; * cseq = sip_cseq_create(home, agent->seq++, SIP_METHOD_OPTIONS); * @endcode * * @return * A pointer to newly created @CSeq * header object when successful or NULL upon an error. */sip_cseq_t *sip_cseq_create(su_home_t *home, uint32_t seq, unsigned method, char const *method_name){ size_t xtra; sip_cseq_t *cs; if (method) method_name = sip_method_name(method, method_name); if (method_name == NULL) return NULL; xtra = (method ? 0 : (strlen(method_name) + 1)); cs = (sip_cseq_t *)sip_header_alloc(home, sip_cseq_class, xtra); if (cs) { cs->cs_seq = seq; cs->cs_method = method; if (!method) method_name = strcpy((char *)(cs + 1), method_name); cs->cs_method_name = method_name; } return cs;}/* ====================================================================== *//**@SIP_HEADER sip_contact Contact Header * * The Contact header contain a list of URLs used to redirect future * requests. Its syntax is defined in @RFC3261 as follows: * * @code * Contact = ("Contact" / "m" ) HCOLON * ( STAR / (contact-param *(COMMA contact-param))) * contact-param = (name-addr / addr-spec) *(SEMI contact-params) * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT * addr-spec = SIP-URI / SIPS-URI / absoluteURI * display-name = *(token LWS)/ quoted-string * contact-params = c-p-q / c-p-expires * / contact-extension * c-p-q = "q" EQUAL qvalue * c-p-expires = "expires" EQUAL delta-seconds * contact-extension = generic-param * delta-seconds = 1*DIGIT * @endcode * * @note * The @RFC2543 syntax allowed <comment>. We accept it, but don't encode it. * * Each parsed Contact header field is stored in #sip_contact_t structure. *//**@ingroup sip_contact * @typedef typedef struct sip_contact_s sip_contact_t; * * The structure #sip_contact_t contains representation of SIP @Contact * header. * * The #sip_contact_t is defined as follows: * @code * typedef struct sip_contact_s { * sip_common_t m_common[1]; // Common fragment info * sip_contact_t *m_next; // Link to next * char const *m_display; // Display name * url_t m_url[1]; // SIP URL * msg_param_t const *m_params; // List of contact-params * char const *m_comment; // Comment * * char const *m_q; // Priority * char const *m_expires; // Expiration time * } sip_contact_t; * @endcode * * @note The <comment> field @ref sip_contact_s::m_comment "m_comment" is * deprecated: it is parsed but not included in encoding. */static msg_xtra_f sip_contact_dup_xtra;static msg_dup_f sip_contact_dup_one;static msg_update_f sip_contact_update;/** @showinitializer */msg_hclass_t sip_contact_class[] = /* * Cut through the fog of macros * SIP_HEADER_CLASS(contact, "Contact", "m", m_params, append, contact); * and show here how the msg_hclass_t is initialized */ {{ /* hc_hash: */ sip_contact_hash, /* hc_parse: */ sip_contact_d, /* hc_print: */ sip_contact_e, /* hc_dxtra: */ sip_contact_dup_xtra, /* hc_dup_one: */ sip_contact_dup_one, /* hc_update: */ sip_contact_update, /* hc_name: */ "Contact", /* hc_len: */ sizeof("Contact") - 1, /* hc_short: */ "m", /* hc_size: */ MSG_ALIGN(sizeof(sip_contact_t), sizeof(void*)), /* hc_params: */ offsetof(sip_contact_t, m_params), /* hc_kind: */ msg_kind_append, /* hc_critical: */ 0 }};issize_t sip_contact_d(su_home_t *home,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -