📄 sip_basic.c
字号:
* @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);int sip_call_id_d(su_home_t *home, sip_header_t *h, char *s, int slen){ sip_call_id_t *i = h->sh_call_id; i->i_id = s; /* XXX - why not sip_word_at_word_d(&s); */ i->i_hash = msg_hash_string(s); return 0;}int sip_call_id_e(char b[], int bsiz, sip_header_t const *h, int flags){ int n = strlen(h->sh_call_id->i_id); if (bsiz > n) strcpy(b, h->sh_call_id->i_id); return n;}/** Extra size of a sip_call_id_t object. */int sip_call_id_dup_xtra(sip_header_t const *h, int offset){ sip_call_id_t const *i = h->sh_call_id; return offset + MSG_STRING_SIZE(i->i_id);}/** * Duplicate a sip_call_id object. * * The function sip_call_id_dup_one() duplicates (deep copies) * a #sip_call_id 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 @c 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, int xtra){ sip_call_id_t *i = dst->sh_call_id; sip_call_id_t const *o = src->sh_call_id; 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); return b;}/**@ingroup sip_call_id * * Create a @b Call-ID header object. * * The function sip_call_id_create() creates 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 * The function sip_call_id_create() returns a pointer to newly created @b * Call-ID header object when successful or NULL upon an error. */sip_call_id_t *sip_call_id_create(su_home_t *home, char const *domain){ sip_call_id_t *i; int xtra = su_guid_strlen + 1 + (domain ? strlen(domain) + 1 : 0); i = sip_header_alloc(home, sip_call_id_class, xtra)->sh_call_id; 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 * *//**@ingroup sip_cseq * @typedef typedef struct sip_cseq_s sip_cseq_t; * * The structure #sip_cseq_t contains representation of SIP @b 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_unknown_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);int sip_cseq_d(su_home_t *home, sip_header_t *h, char *s, int slen){ sip_cseq_t *cs = h->sh_cseq; 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;}int sip_cseq_e(char b[], int bsiz, sip_header_t const *h, int flags){ assert(sip_is_cseq(h)); return snprintf(b, bsiz, "%u %s", h->sh_cseq->cs_seq, h->sh_cseq->cs_method_name);}int sip_cseq_dup_xtra(sip_header_t const *h, int offset){ sip_cseq_t const *cs = h->sh_cseq; 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, int xtra){ sip_cseq_t *cs = dst->sh_cseq; sip_cseq_t const *o = src->sh_cseq; 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); return b;}/**@ingroup sip_cseq * *燙reate a @b CSeq header object. * * The function sip_cseq_create() creates 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 * The function sip_cseq_create() returns a pointer to newly created @b 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_header_alloc(home, sip_cseq_class, xtra)->sh_cseq; 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 [S10.14] 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. *//**@ingroup sip_contact * @typedef typedef struct sip_contact_s sip_contact_t; * * The structure #sip_contact_t contains representation of SIP @b 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 * * msg_param_t m_q; // Priority * msg_param_t m_expires; // Expiration time * } sip_contact_t; * @endcode * * @note: The field @ref sip_contact_s::m_comment m_comment is deprecated. */static msg_xtra_f sip_contact_dup_xtra;static msg_dup_f sip_contact_dup_one;static msg_update_f sip_contact_update;msg_hclass_t sip_contact_class[] = SIP_HEADER_CLASS(contact, "Contact", "m", m_params, append, contact);int sip_contact_d(su_home_t *home, sip_header_t *h, char *s, int slen){ sip_header_t **hh = &h->sh_succ, *h0 = h; sip_contact_t *m = h->sh_contact; assert(h); for (;*s;) { /* Ignore empty entries (comma-whitespace) */ if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; } if (!h) { /* If there are multiple contacts on one line * we must allocate next header structure */ if (!(h = sip_header_alloc(home, h0->sh_class, 0))) return -1; *hh = h; h->sh_prev = hh; hh = &h->sh_succ; m = m->m_next = h->sh_contact; } if (sip_name_addr_d(home, &s, &m->m_display, m->m_url, &m->m_params, &m->m_comment) == -1) return -1; if (*s != '\0' && *s != ',') return -1; if (m->m_params) msg_header_update_params(m->m_common, 0); h = NULL; } if (h) /* Empty list is an error */ return -1; return 0;}int sip_contact_e(char b[], int bsiz, sip_header_t const *h, int flags){ sip_contact_t const *m = h->sh_contact; int always_lt_gt = MSG_IS_CANONIC(flags) && m->m_url->url_type != url_any; assert(sip_is_contact(h)); return sip_name_addr_e(b, bsiz, flags, m->m_display, always_lt_gt, m->m_url, m->m_params, NULL /* m->m_comment */);}int sip_contact_dup_xtra(sip_header_t const *h, int offset){ int rv = offset; sip_contact_t const *m = h->sh_contact; MSG_PARAMS_SIZE(rv, m->m_params); rv += MSG_STRING_SIZE(m->m_display); rv += url_xtra(m->m_url); rv += MSG_STRING_SIZE(m->m_comment); return rv;}char *sip_contact_dup_one(sip_header_t *dst, sip_header_t const *src, char *b, int xtra){ char *end = b + xtra; sip_contact_t *m = dst->sh_contact; sip_contact_t const *o = src->sh_contact; b = msg_params_dup(&m->m_params, o->m_params, b, xtra); MSG_STRING_DUP(b, m->m_display, o->m_display); URL_DUP(b, end, m->m_url, o->m_url); MSG_STRING_DUP(b, m->m_comment, o->m_comment); assert(b <= end); return b;}/** Update parameter in sip_contact_t */static int sip_contact_update(msg_common_t *h, char const *name, int namelen, char const *value){ sip_contact_t *m = (sip_contact_t *)h; if (name == NULL) { m->m_q = NULL; m->m_expires = NULL; } else if (namelen == 1 && strncasecmp(name, "q", 1) == 0) { /* XXX - check for invalid value? */ m->m_q = value; } else if (namelen == strlen("expires") && !strncasecmp(name, "expires", namelen)) { m->m_expires = value; } return 0;}/**@ingroup sip_contact * * Add a parameter to a @b Contact header object * * The function sip_contact_add_param() adds a parameter to a contact * object. It does not copy the contents of the string @c param. * * @note This function @b does @b not duplicate @p param. * * @param home memory home * @param m sip_contact_t object * @param param parameter string * * @return 0 when successful, and -1 upon an error. * * @deprecated Use msg_header_replace_param() directly. */int sip_contact_add_param(su_home_t *home, sip_contact_t *m, char const *param){ return msg_header_replace_param(home, m->m_common, param);}/* ====================================================================== *//**@SIP_HEADER sip_content_length Content-Length Header * * The Content-Length header indicates the size of the message-body in * decimal number of octets. Its syntax is defined in [S10.18] as * follows: * * @code * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -