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

📄 test_proxy.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 2 页
字号:
  int status;  auth_status_t *as;  msg_t *msg;  as = auth_status_new(p->home);  if (!as)    return 500;  as->as_method = sip->sip_request->rq_method_name;  msg = nta_incoming_getrequest(irq);  as->as_source = msg_addrinfo(msg);  as->as_user_uri = sip->sip_from->a_url;  as->as_display = sip->sip_from->a_display;  if (sip->sip_payload)    as->as_body = sip->sip_payload->pl_data,      as->as_bodylen = sip->sip_payload->pl_len;  auth_mod_check_client(p->auth, as, sip->sip_proxy_authorization,			proxy_challenger);  if ((status = as->as_status)) {    nta_incoming_treply(irq,			as->as_status, as->as_phrase,			SIPTAG_HEADER((void *)as->as_info),			SIPTAG_HEADER((void *)as->as_response),			TAG_END());  }  else if (as->as_match) {    msg_header_remove(msg, NULL, as->as_match);  }  msg_destroy(msg);  su_home_unref(as->as_home);  return status;}		      int proxy_ack_cancel(struct proxy_transaction *t,		     nta_incoming_t *irq,		     sip_t const *sip){  if (sip == NULL) {    proxy_transaction_destroy(t);    return 0;  }  if (sip->sip_request->rq_method == sip_method_cancel) {    /* We don't care about response to CANCEL (or ACK)     * so we give NULL as callback pointer (and nta immediately      * destroys transaction object or marks it disposable)     */    if (nta_outgoing_tcancel(t->client, NULL, NULL, TAG_END()))      return 200;    else      return 500;  }  else {    return 500;  }}int proxy_response(struct proxy_transaction *t,		   nta_outgoing_t *client,		   sip_t const *sip){  int final;  if (sip) {    msg_t *response = nta_outgoing_getresponse(client);    final = sip->sip_status->st_status >= 200;    sip_via_remove(response, sip_object(response));    nta_incoming_mreply(t->server, response);  }  else {    final = 1;    nta_incoming_treply(t->server, SIP_408_REQUEST_TIMEOUT, TAG_END());  }  if (final)    proxy_transaction_destroy(t);  return 0;}struct proxy_transaction *proxy_transaction_new(struct proxy *proxy){  struct proxy_transaction *t;  t = su_zalloc(proxy->home, sizeof *t);  if (t) {    t->proxy = proxy;    proxy_transaction_insert(&proxy->transactions, t);  }  return t;}staticvoid proxy_transaction_destroy(struct proxy_transaction *t){  if (t == t->proxy->stateless)    return;  proxy_transaction_remove(t);  nta_incoming_destroy(t->server);  nta_outgoing_destroy(t->client);  su_free(t->proxy->home, t->rq);  su_free(t->proxy->home, t);}LIST_BODIES(static, proxy_transaction, struct proxy_transaction, next, prev);/* ---------------------------------------------------------------------- */staticint domain_request(struct proxy *proxy,		   nta_leg_t *leg,		   nta_incoming_t *irq,		   sip_t const *sip){  sip_method_t method = sip->sip_request->rq_method;  if (method == sip_method_register)    return process_register(proxy, irq, sip);  if (method == sip_method_options)     return process_options(proxy, irq, sip);  return 501;}staticint process_options(struct proxy *proxy,		    nta_incoming_t *irq,		    sip_t const *sip){  nta_incoming_treply(irq, SIP_200_OK,		      SIPTAG_CONTACT(proxy->transport_contacts),		      TAG_END());  return 200;}/* ---------------------------------------------------------------------- */static int process_register2(struct proxy *p, auth_status_t *as,			      nta_incoming_t *irq, sip_t const *sip);static int set_status(auth_status_t *as, int status, char const *phrase);static int validate_contacts(struct proxy *p, auth_status_t *as,			     sip_t const *sip);static int check_out_of_order(struct proxy *p, auth_status_t *as,			      struct registration_entry *e, sip_t const *);static int binding_update(struct proxy *p,       		   auth_status_t *as,       		   struct registration_entry *e,       		   sip_t const *sip);sip_contact_t *binding_contacts(su_home_t *home, struct binding *bindings);int process_register(struct proxy *proxy,       	      nta_incoming_t *irq,       	      sip_t const *sip){  auth_status_t *as;  msg_t *msg;  int status;  as = auth_status_new(proxy->home);  if (!as)    return 500;  as->as_method = sip->sip_request->rq_method_name;  msg = nta_incoming_getrequest(irq);  as->as_source = msg_addrinfo(msg);  msg_destroy(msg);  as->as_user_uri = sip->sip_from->a_url;  as->as_display = sip->sip_from->a_display;  if (sip->sip_payload)    as->as_body = sip->sip_payload->pl_data,      as->as_bodylen = sip->sip_payload->pl_len;  process_register2(proxy, as, irq, sip);  assert(as->as_status >= 200);  nta_incoming_treply(irq,       	       as->as_status, as->as_phrase,       	       SIPTAG_HEADER((void *)as->as_info),       	       SIPTAG_HEADER((void *)as->as_response),       	       TAG_END());  status = as->as_status;  su_home_unref(as->as_home);  return status;}static int process_register2(struct proxy *p,			     auth_status_t *as,			     nta_incoming_t *irq,			     sip_t const *sip){  struct registration_entry *e = NULL;  auth_mod_check_client(p->auth, as, sip->sip_authorization,			registrar_challenger);  if (as->as_status)    return as->as_status;  assert(as->as_response == NULL);  if (validate_contacts(p, as, sip))    return as->as_status;  e = registration_entry_find(p, sip->sip_to->a_url);  if (!sip->sip_contact) {    as->as_response = (msg_header_t *)e->contacts;    return set_status(as, SIP_200_OK);  }  if (e && check_out_of_order(p, as, e, sip))    return as->as_status;    if (!e)     e = registration_entry_new(p, sip->sip_to->a_url);  if (!e)    return set_status(as, SIP_500_INTERNAL_SERVER_ERROR);  if (binding_update(p, as, e, sip))    return as->as_status;  msg_header_free(p->home, (void *)e->contacts);  e->contacts = binding_contacts(p->home, e->bindings);  as->as_response = (msg_header_t *)e->contacts;  return set_status(as, SIP_200_OK);}static int set_status(auth_status_t *as, int status, char const *phrase){  return as->as_phrase = phrase, as->as_status = status;}static int validate_contacts(struct proxy *p,			     auth_status_t *as,			     sip_t const *sip){  sip_contact_t const *m;  sip_time_t expires;  sip_time_t now = sip_now();  for (m = sip->sip_contact; m; m = m->m_next) {    if (m->m_url->url_type == url_any) {      if (!sip->sip_expires ||	  sip->sip_expires->ex_delta || 	  sip->sip_expires->ex_time ||	  sip->sip_contact->m_next)	return set_status(as, SIP_400_BAD_REQUEST);      else	return 0;    }    expires = sip_contact_expires(m, sip->sip_expires, sip->sip_date,				  p->prefs.expires, now);        if (expires > 0 && expires < p->prefs.min_expires) {      as->as_response = (msg_header_t *)	sip_min_expires_format(as->as_home, "%u", 			       (unsigned)p->prefs.min_expires);      return set_status(as, SIP_423_INTERVAL_TOO_BRIEF);    }  }  return 0;}/** Check for out-of-order register request */staticint check_out_of_order(struct proxy *p,		       auth_status_t *as,		       struct registration_entry *e,		       sip_t const *sip){  struct binding const *b;  sip_call_id_t const *id;  sip_contact_t *m;  if (e == NULL || !sip->sip_contact)    return 0;  id = sip->sip_call_id;    /* RFC 3261 subsection 10.3 step 6 and step 7 (p. 66): */  /* Check for reordered register requests */  for (b = e->bindings; b; b = b->next) {    if (binding_is_active(b) &&	strcmp(sip->sip_call_id->i_id, b->call_id->i_id) == 0 &&	sip->sip_cseq->cs_seq <= b->cseq) {      for (m = sip->sip_contact; m; m = m->m_next) {	if (m->m_url->url_type == url_any ||	    url_cmp_all(m->m_url, b->contact->m_url) == 0)	  return set_status(as, SIP_500_INTERNAL_SERVER_ERROR);      }    }  }  return 0;}static struct registration_entry *registration_entry_find(struct proxy const *proxy, url_t const *uri){  struct registration_entry *e;  /* Our routing table */  for (e = proxy->entries; e; e = e->next) {    if (url_cmp(uri, e->aor) == 0)      return e;  }  return NULL;}static struct registration_entry *registration_entry_new(struct proxy *proxy, url_t const *aor){  struct registration_entry *e;  e = su_zalloc(proxy->home, sizeof *e);   if (!e)     return NULL;  e->proxy = proxy;  e->aor = url_hdup(proxy->home, aor);  if (!e->aor) {    su_free(proxy->home, e);    return NULL;  }  registration_entry_insert(&proxy->entries, e);  return e;}static voidregistration_entry_destroy(struct registration_entry *e){  if (e) {    registration_entry_remove(e);    su_free(e->proxy->home, e->aor);    while (e->bindings)      binding_destroy(e->proxy->home, e->bindings);    msg_header_free(e->proxy->home, (void *)e->contacts);    su_free(e->proxy->home, e);  }}LIST_BODIES(static, registration_entry, struct registration_entry, next, prev);/* ---------------------------------------------------------------------- *//* Bindings */staticstruct binding *binding_new(su_home_t *home, 			    sip_contact_t *contact,			    sip_call_id_t *call_id,			    uint32_t cseq,			    sip_time_t registered, 			    sip_time_t expires){  struct binding *b;    b = su_zalloc(home, sizeof *b);  if (b) {    sip_contact_t m[1];    *m = *contact; m->m_next = NULL;    b->contact = sip_contact_dup(home, m);    b->call_id = sip_call_id_dup(home, call_id);    b->cseq = cseq;    b->registered = registered;    b->expires = expires;    if (!b->contact || !b->call_id)      binding_destroy(home, b), b = NULL;    if (b)      msg_header_remove_param(b->contact->m_common, "expires");  }    return b;}staticvoid binding_destroy(su_home_t *home, struct binding *b){  if (b->prev) {    if ((*b->prev = b->next))      b->next->prev = b->prev;  }  msg_header_free(home, (void *)b->contact);  msg_header_free(home, (void *)b->call_id);  su_free(home, b);}staticint binding_update(struct proxy *p,		   auth_status_t *as,		   struct registration_entry *e,		   sip_t const *sip){  struct binding *b, *old, *next, *last, *bindings = NULL, **bb = &bindings;  sip_contact_t *m;  sip_time_t expires;  sip_time_t now = sip_now();  assert(sip->sip_contact);  /* Create new bindings */  for (m = sip->sip_contact; m; m = m->m_next) {    if (m->m_url->url_type == url_any)      break;        expires = sip_contact_expires(m, sip->sip_expires, sip->sip_date,				  p->prefs.expires, now);    if (expires > p->prefs.max_expires)      expires = p->prefs.max_expires;    msg_header_remove_param(m->m_common, "expires");    b = binding_new(p->home, m, sip->sip_call_id, sip->sip_cseq->cs_seq, 		    now, now + expires);    if (!b)      break;    *bb = b, b->prev = bb, bb = &b->next;  }  last = NULL;  if (m == NULL) {    /* Merge new bindings with old ones */    for (old = e->bindings; old; old = next) {      next = old->next;      for (b = bindings; b != last; b = b->next) {	if (url_cmp_all(old->contact->m_url, b->contact->m_url) != 0) 	  continue;	if (strcmp(old->call_id->i_id, b->call_id->i_id) == 0) {	  b->registered = old->registered;	}	binding_destroy(p->home, old);	break;      }    }    for (bb = &e->bindings; *bb; bb = &(*bb)->next)      ;    if ((*bb = bindings))      bindings->prev = bb;  }  else if (m->m_url->url_type == url_any) {    /* Unregister all */    for (b = e->bindings; b; b = b->next) {      b->expires = now;    }  }  else {    /* Infernal error */    for (old = bindings; old; old = next) {      next = old->next;      binding_destroy(p->home, old);    }    return set_status(as, SIP_500_INTERNAL_SERVER_ERROR);  }  return 0;}sip_contact_t *binding_contacts(su_home_t *home, struct binding *bindings){  sip_contact_t *retval = NULL, **mm = &retval;   struct binding *b;  sip_time_t now = sip_now();  for (b = bindings; b; b = b->next) {    char const *expires;    if (b->expires <= now)      continue;    *mm = sip_contact_copy(home, b->contact);    if (*mm) {      expires = su_sprintf(home, "expires=%u", (unsigned)(b->expires - now));      msg_header_add_param(home, (*mm)->m_common, expires);      mm = &(*mm)->m_next;    }  }  return retval;}

⌨️ 快捷键说明

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