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

📄 sip_util.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
  while (q[0] == '0')    q++;  if (q[0] >= '1' && q[0] <= '9')    return 1000;  if (q[0] == '\0')    return 0;  if (q[0] != '.')          return 500;    /* Garbage... */  if (q[1] >= '0' && q[1] <= '9') {    value = (q[1] - '0') * 100;    if (q[2] >= '0' && q[2] <= '9') {      value += (q[2] - '0') * 10;      if (q[3] >= '0' && q[3] <= '9') {	value += (q[3] - '0');	if (q[4] > '5' && q[4] <= '9')	  /* Round upwards */	  value += 1;	else if (q[4] == '5') 	  value += value & 1; /* Round to even */      }    }  }  return value;}/**@ingroup sip_route * * Get first route header and remove it from its fragment chain.  * */sip_route_t *sip_route_remove(msg_t *msg, sip_t *sip){  sip_route_t *r;  if ((r = sip->sip_route))    msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)r);  return r;}/**@ingroup sip_route * * Get last route header and remove it from its fragment chain.  * */sip_route_t *sip_route_pop(msg_t *msg, sip_t *sip){  sip_route_t *r;  for (r = sip->sip_route; r; r = r->r_next)     if (r->r_next == NULL) {      msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)r);      return r;    }  return NULL;}/**@ingroup sip_route * * Get first route header and rewrite the RequestURI.  */sip_route_t *sip_route_follow(msg_t *msg, sip_t *sip){  if (sip->sip_route) {    /* XXX - in case of outbound proxy, route may contain our address */           sip_route_t *r = sip_route_remove(msg, sip);    sip_request_t *rq = sip->sip_request;    rq = sip_request_create(msg_home(msg), rq->rq_method, rq->rq_method_name,			    (url_string_t const *)r->r_url, rq->rq_version);    url_strip_transport(rq->rq_url);    msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)rq);    return r;  }  return NULL;}/**@ingroup sip_route *  * Check if route header has lr param. * * "lr" param can be either URL or header parameter. */int sip_route_is_loose(sip_route_t const *r){  if (!r)    return 0;  if (r->r_url->url_params)    return url_has_param(r->r_url, "lr");  else    return r->r_params && msg_params_find(r->r_params, "lr") != NULL;}/**@ingroup sip_route * * Reverse a route header.  * * The function sip_route_reverse() reverses a route header like @b * Record-Route or @b Path. */sip_route_t *sip_route_reverse(su_home_t *home, sip_route_t const *route){  sip_route_t *reverse = NULL;  sip_route_t r[1], *tmp;  sip_route_init(r);  for (reverse = NULL; route; route = route->r_next) {    *r->r_url = *route->r_url;    /* Fix broken (Record-)Routes without <> */    if (r->r_url->url_params == NULL	&& r->r_params 	&& r->r_params[0] 	&& (r->r_params[0][0] == 'l' || r->r_params[0][0] == 'L')	&& (r->r_params[0][1] == 'r' || r->r_params[0][1] == 'R')	&& (r->r_params[0][2] == '=' || r->r_params[0][2] == 0))      r->r_url->url_params = route->r_params[0],	r->r_params = route->r_params + 1;    else      r->r_params = route->r_params;    tmp = sip_route_dup(home, r);    if (!tmp)       goto error;    tmp->r_next = reverse;    reverse = tmp;  }  return reverse; error:  while (reverse) {    sip_route_t *r_next = reverse->r_next;    su_free(home, reverse);    reverse = r_next;  }  return NULL;}/**@ingroup sip_route * * Fix and duplicate a route header.  * * The function sip_route_reverse() reverses a route header like @b * Record-Route or @b Path. * */sip_route_t *sip_route_fixdup(su_home_t *home, sip_route_t const *route){  sip_route_t *copy = NULL;  sip_route_t r[1], **rr;  sip_route_init(r);  /* Copy the record route as route */  for (rr = &copy; route; route = route->r_next) {    *r->r_url = *route->r_url;    /* Fix broken (Record-)Routes without <> */    if (r->r_url->url_params == NULL	&& r->r_params 	&& r->r_params[0] 	&& (r->r_params[0][0] == 'l' || r->r_params[0][0] == 'L')	&& (r->r_params[0][1] == 'r' || r->r_params[0][1] == 'R')	&& (r->r_params[0][2] == '=' || r->r_params[0][2] == 0))      r->r_url->url_params = route->r_params[0],	r->r_params = route->r_params + 1;    else      r->r_params = route->r_params;    *rr = sip_route_dup(home, r);    if (!*rr) goto error;    rr = &(*rr)->r_next;  }  return copy; error:  while (copy) {    sip_route_t *r_next = copy->r_next;    su_free(home, copy);    copy = r_next;  }  return NULL;}static void sip_fragment_clear_chain(sip_header_t *h){  void const *next;  for (h = h; h; h = h->sh_succ) {    next = (char *)h->sh_data + h->sh_len;    sip_fragment_clear(h->sh_common);    if (!next ||	!h->sh_succ ||	h->sh_next != h->sh_succ ||	h->sh_succ->sh_data != next ||	h->sh_succ->sh_len)      return;  }}/**@ingroup sip_route * * Fix Route header. */sip_route_t *sip_route_fix(sip_route_t *route){  sip_route_t *r;  sip_header_t *h = NULL;  int i;  for (r = route; r; r = r->r_next) {    /* Keep track of first header structure on this header line */    if (!h 	|| (char *)h->sh_data + h->sh_len != r->r_common->h_data	|| r->r_common->h_len)      h = (sip_header_t *)r;    if (r->r_url->url_params == NULL	&& r->r_params 	&& r->r_params[0] 	&& (r->r_params[0][0] == 'l' || r->r_params[0][0] == 'L')	&& (r->r_params[0][1] == 'r' || r->r_params[0][1] == 'R')	&& (r->r_params[0][2] == '=' || r->r_params[0][2] == 0)) {      r->r_url->url_params = r->r_params[0];      for (i = 0; r->r_params[i]; i++)	((char const **)r->r_params)[i] = r->r_params[i + 1];      sip_fragment_clear_chain(h);    }  }  return route;}/**@ingroup sip_via * * Get first via header and remove it from its fragment chain.  */sip_via_t *sip_via_remove(msg_t *msg, sip_t *sip){  sip_via_t *v;  if (sip == NULL)    return NULL;    for (v = sip->sip_via; v; v = v->v_next) {    sip_fragment_clear(v->v_common);    if (v->v_next != (void *)v->v_common->h_succ)      break;  }  if ((v = sip->sip_via))    msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)v);  return v;}/** Serialize payload. * * The sip_payload_serialize() adds missing headers to MIME multiparty payload, * encodes them and orders them in header chain.  It also calculates the total * length of the payload. */unsigned long sip_payload_serialize(msg_t *msg, sip_payload_t *pl){  unsigned long total;  for (total = 0; pl; pl = (sip_payload_t *)pl->pl_next) {    total += (unsigned)pl->pl_common->h_len;  }  return total;}/**  * Remove extra parameters from an AOR URL. * * The extra parameters listed in the RFC 3261 table 1 include port number, * method, maddr, ttl, transport, lr and headers. *  * @note The funtion modifies the @a url and the strings attached to it. * * @retval 0 when successful * @retval -1 upon an error */int sip_aor_strip(url_t *url){  if (url == NULL)    return -1;  url->url_port = NULL;  url->url_headers = NULL;  if (url->url_params) {    char *d, *s;    size_t n;    int semi;#   define PARAM_MATCH(s, tag)						\    (strncasecmp(s, tag, strlen(tag)) == 0 &&				\     (s[strlen(tag)] == '\0' ||						\      s[strlen(tag)] == ';' ||						\      s[strlen(tag)] == '='))    for (d = s = (char *)url->url_params; *s; s += n + semi) {      n = strcspn(s, ";");      semi = s[n] != '\0';          if (PARAM_MATCH(s, "method"))	continue;      if (PARAM_MATCH(s, "maddr"))	continue;      if (PARAM_MATCH(s, "ttl"))	continue;      if (PARAM_MATCH(s, "transport"))	continue;      if (PARAM_MATCH(s, "lr"))	continue;      if (s != d) {	if (d != url->url_params)	  d++;	if (s != d)	  memcpy(d, s, n + 1);      }      d += n;    }    if (d == url->url_params)      url->url_params = NULL;    else if (d != s)      *d = '\0';#   undef PARAM_MATCH  }  return 0;}/** Compare Security-Verify header with Security-Server header. */int sip_security_verify_compare(sip_security_server_t const *s,				sip_security_verify_t const *v,				msg_param_t *return_d_ver){  int i, j, retval, digest;  msg_param_t const *s_params, *v_params, empty[] = { NULL };  if (return_d_ver)    *return_d_ver = NULL;  if (s == NULL)    return 0;  for (;;s = s->sa_next, v = v->sa_next) {    if (s == NULL || v == NULL)      return (s == NULL) - (v == NULL);        if ((retval = str0cmp(s->sa_mec, v->sa_mec)))      return retval;    digest = strcasecmp(s->sa_mec, "Digest") == 0;    s_params = s->sa_params, v_params = v->sa_params;    if (digest && s_params == NULL && v_params != NULL)      s_params = empty;    if (s_params == NULL || v_params == NULL) {      if ((retval = (s_params == NULL) - (v_params == NULL)))	return retval;      continue;    }    for (i = 0, j = 0;; i++, j++) {      if (digest && v_params[j] && 	  strncasecmp(v_params[j], "d-ver=", 6) == 0) {	if (return_d_ver)	  *return_d_ver = v_params[j] + strlen("d-ver=");	j++;      }      retval = str0cmp(s_params[i], v_params[j]);            if (retval || s_params[i] == NULL || v_params[j] == NULL) 	break;    }    if (retval)      return retval;  }}/** Select best mechanism from Security-Client header.  * * @note We assume that Security-Server header in @a s is sorted by * preference. */sip_security_client_t const *sip_security_client_select(sip_security_client_t const *client,			   sip_security_server_t const *server){  sip_security_server_t const *c, *s;  if (server == NULL || client == NULL)    return NULL;  for (s = server; s; s = s->sa_next) {    for (c = client; c; c = c->sa_next) {      if (str0cmp(s->sa_mec, c->sa_mec) == 0)	return c;    }  }  return NULL;}/**Checks if the response with given response code terminates dialog or * dialog usage. *  * @return -1 if the response with given code terminates whole dialog. * @return 1 if the response terminates the dialog usage. * @return 0 if the response does not terminate dialog or dialog usage. *  * @return * The @a *return_graceful_terminate_usage is set to 1, if application * should gracefully terminate its dialog usage. It is set to 0, if no * graceful terminate is required. If it is up to application policy to * decide whether to gracefully terminate or not, the * @a *return_graceful_terminate_usage is left unmodified. * * @sa  * http://www.ietf.org/internet-drafts/draft-sparks-sipping-dialogusage-01.txt */int sip_response_terminates_dialog(int response_code,				   sip_method_t method,				   int *return_graceful_terminate_usage){  enum { no_effect, terminate_usage = 1, terminate_dialog = -1 };  int dummy;  if (!return_graceful_terminate_usage)     return_graceful_terminate_usage = &dummy;  if (response_code < 300)    return *return_graceful_terminate_usage = 0;  /*        3xx responses: Redirection mid-dialog is not well understood in SIP,      but whatever effect it has impacts the entire dialog and all of

⌨️ 快捷键说明

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