⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_parser.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
  sip_method_name_publish,  /* If you add something here, add also them to sip_method_d! */  NULL};/** Get canonic method name. */char const *sip_method_name(sip_method_t method, char const *name){  const size_t N = sizeof(sip_method_names)/sizeof(sip_method_names[0]);  if (method > 0 && (size_t)method <= N)    return sip_method_names[method];  else if (method == 0)    return name;  else    return NULL;}/**Parse a SIP method name. * * Parse a SIP method name and return a code corresponding to the method.  * The address of the first non-LWS character after method name is stored in * @a *ss. * * @param ss    pointer to pointer to string to be parsed * @param return_name  value-result parameter for method name * * @note * If there is no whitespace after method name, the value in @a *return_name * may not be NUL-terminated.  The calling function @b must NUL terminate * the value by setting the @a **ss to NUL after first examining its value. * * @return The method code if method * was identified, 0 (sip_method_unknown()) if method is not known, or @c -1 * (sip_method_invalid()) if an error occurred. * * If the value-result argument @a return_name is not @c NULL, * a pointer to the method name is stored to it. */sip_method_t sip_method_d(char **ss, char const **return_name){  char *s = *ss, c = *s;  char const *name;  int code = sip_method_unknown;  size_t n = 0;#define MATCH(s, m) (strncmp(s, m, n = sizeof(m) - 1) == 0)  switch (c) {  case 'A': if (MATCH(s, "ACK")) code = sip_method_ack; break;  case 'B': if (MATCH(s, "BYE")) code = sip_method_bye; break;  case 'C':     if (MATCH(s, "CANCEL"))       code = sip_method_cancel;     break;  case 'I':     if (MATCH(s, "INVITE"))      code = sip_method_invite;    else if (MATCH(s, "INFO"))      code = sip_method_info;    break;  case 'M': if (MATCH(s, "MESSAGE")) code = sip_method_message; break;  case 'N': if (MATCH(s, "NOTIFY")) code = sip_method_notify; break;  case 'O': if (MATCH(s, "OPTIONS")) code = sip_method_options; break;  case 'P':     if (MATCH(s, "PRACK")) code = sip_method_prack;     else if (MATCH(s, "PUBLISH")) code = sip_method_publish;     break;  case 'R':     if (MATCH(s, "REGISTER"))       code = sip_method_register;     else if (MATCH(s, "REFER"))      code = sip_method_refer;     break;  case 'S':     if (MATCH(s, "SUBSCRIBE"))       code = sip_method_subscribe;     break;  case 'U':    if (MATCH(s, "UPDATE"))      code = sip_method_update;    break;  }#undef MATCH  if (IS_NON_WS(s[n]))     /* Unknown method */    code = sip_method_unknown;  if (code == sip_method_unknown) {    name = s;    for (n = 0; IS_UNRESERVED(s[n]); n++)      ;    if (s[n]) {      if (!IS_LWS(s[n]))	return sip_method_invalid;      if (return_name)	s[n++] = '\0';    }  }  else {    name = sip_method_names[code];  }  while (IS_LWS(s[n]))    n++;  *ss = (s + n);  if (return_name) *return_name = name;  return code;}/** Get method enum corresponding to method name */sip_method_t sip_method_code(char const *name){  /* Note that sip_method_d() does not change string if return_name is NULL */  return sip_method_d((char **)&name, NULL);}char const sip_transport_udp[] = "SIP/2.0/UDP";char const sip_transport_tcp[] = "SIP/2.0/TCP";char const sip_transport_sctp[] = "SIP/2.0/SCTP";char const sip_transport_tls[] = "SIP/2.0/TLS";/** Decode transport */issize_t sip_transport_d(char **ss, char const **ttransport){  char const *transport;  char *pn, *pv, *pt;  size_t pn_len, pv_len, pt_len;  char *s = *ss;#define TRANSPORT_MATCH(t)					     \  (strncasecmp(s+7, t+7, sizeof(t)-8) == 0 && (IS_LWS(s[sizeof(t)])) \   && (transport = t, s += sizeof(t) - 1))  if (strncasecmp(s, "SIP/2.0", 7) != 0 ||      (!TRANSPORT_MATCH(sip_transport_udp) &&       !TRANSPORT_MATCH(sip_transport_tcp) &&       !TRANSPORT_MATCH(sip_transport_sctp) &&       !TRANSPORT_MATCH(sip_transport_tls))) {    /* Protocol name */     transport = pn = s;    skip_token(&s);    pn_len = s - pn;    skip_lws(&s);    if (pn_len == 0 || *s++ != '/') return -1;    skip_lws(&s);        /* Protocol version */    pv = s;    skip_token(&s);    pv_len = s - pv;    skip_lws(&s);    if (pv_len == 0 || *s++ != '/') return -1;    skip_lws(&s);        /* Transport protocol */    pt = s;    skip_token(&s);    pt_len = s - pt;    if (pt_len == 0) return -1;        /* Remove whitespace between protocol name and version */    if (pn + pn_len + 1 != pv) {      pn[pn_len] = '/';      pv = memmove(pn + pn_len + 1, pv, pv_len);    }    /* Remove whitespace between protocol version and transport */    if (pv + pv_len + 1 != pt) {      pv[pv_len] = '/';      pt = memmove(pv + pv_len + 1, pt, pt_len);      pt[pt_len] = '\0';            /* extra whitespace? */      if (!strcasecmp(transport, sip_transport_udp))	transport = sip_transport_udp;      else if (!strcasecmp(transport, sip_transport_tcp))	transport = sip_transport_tcp;      else if (!strcasecmp(transport, sip_transport_sctp))	transport = sip_transport_sctp;      else if (!strcasecmp(transport, sip_transport_tls))	transport = sip_transport_tls;    }  }  if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); }  *ss = s;  *ttransport = transport;  return 0;}/** Calculate extra space required by sip_transport_dup() */isize_t sip_transport_xtra(char const *transport){  if (transport == sip_transport_udp ||      transport == sip_transport_tcp ||      transport == sip_transport_sctp ||      transport == sip_transport_tls ||      strcasecmp(transport, sip_transport_udp) == 0 ||      strcasecmp(transport, sip_transport_tcp) == 0 ||      strcasecmp(transport, sip_transport_sctp) == 0 ||      strcasecmp(transport, sip_transport_tls) == 0)    return 0;  return MSG_STRING_SIZE(transport);}/** Duplicate a transport string */void sip_transport_dup(char **pp, char const **dd, char const *s){  if (s == sip_transport_udp)    *dd = s;  else if (s == sip_transport_tcp)    *dd = s;  else if (s == sip_transport_sctp)    *dd = s;  else if (s == sip_transport_tls)    *dd = s;  else if (strcasecmp(s, sip_transport_udp) == 0)    *dd = sip_transport_udp;  else if (strcasecmp(s, sip_transport_tcp) == 0)    *dd = sip_transport_tcp;  else if (strcasecmp(s, sip_transport_sctp) == 0)    *dd = sip_transport_sctp;  else if (strcasecmp(s, sip_transport_tls) == 0)    *dd = sip_transport_tls;  else    MSG_STRING_DUP(*pp, *dd, s);}/** Parse SIP <word "@" word> construct used in @CallID. */char *sip_word_at_word_d(char **ss){  char *rv = *ss, *s0 = *ss;  skip_word(ss);  if (s0 == *ss)    return NULL;  if (**ss == '@') {    (*ss)++;    s0 = *ss;    skip_word(ss);    if (s0 == *ss)      return NULL;  }  if (IS_LWS(**ss))    (*ss)++;  skip_lws(ss);  return rv;}/**Add message separator, then test if message is complete.  * * Add sip_content_length and sip_separator if they are missing.  * The test that all necessary message components ( @From, @To, * @CSeq, @CallID, @ContentLength and message separator are present. * * @retval 0 when successful * @retval -1 upon an error: headers are missing and they could not be added */int sip_complete_message(msg_t *msg){  sip_t *sip = sip_object(msg);  su_home_t *home = msg_home(msg);  size_t len = 0;  ssize_t mplen;  if (sip == NULL)    return -1;  if (!sip->sip_separator)    sip->sip_separator = sip_separator_create(msg_home(msg));  if (sip->sip_multipart) {    sip_content_type_t *c = sip->sip_content_type;    msg_multipart_t *mp = sip->sip_multipart;    sip_common_t *head;    if (!c || msg_multipart_complete(msg_home(msg), c, mp) < 0)      return -1;    if (sip->sip_payload)      head = sip->sip_payload->pl_common;    else      head = sip->sip_separator->sep_common;    if (!head || !msg_multipart_serialize(&head->h_succ, mp))      return -1;    mplen = msg_multipart_prepare(msg, mp, sip->sip_flags);    if (mplen == -1)      return -1;    len = (size_t)mplen;  }   if (sip->sip_payload)    len += sip->sip_payload->pl_len;  if (len > UINT32_MAX)    return -1;  if (!sip->sip_content_length) {    msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t*)		      sip_content_length_create(home, (uint32_t)len));  }  else {    if (sip->sip_content_length->l_length != len) {      sip->sip_content_length->l_length = (uint32_t)len;      sip_fragment_clear(sip->sip_content_length->l_common);    }  }    if (!sip->sip_cseq ||       !sip->sip_call_id ||      !sip->sip_to ||      !sip->sip_from ||      !sip->sip_separator ||      !sip->sip_content_length)    return -1;    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -