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

📄 nea_server.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
 * @param nes pointer to notifier * @param local_target optional contact header  * @param msg pointer to request message * @param sip pointer to SIP view to request message * * @return  * The function nea_server_add() returns 0 if successful, -1 upon an * error. *   */int nea_server_add(nea_server_t *nes, 		   sip_contact_t const *local_target,		   msg_t *msg, sip_t *sip){  su_home_t *home = nes->nes_home;  nea_sub_t *s = NULL;  url_t target[1];  s = nea_sub_create(nes);  s->s_from = sip_from_dup(home, sip->sip_from);  if (local_target == NULL)    local_target = nes->nes_eventity_uri;  s->s_local = sip_contact_dup(nes->nes_home, local_target);  *target = *local_target->m_url;  s->s_leg = nta_leg_tcreate(nes->nes_agent, nea_sub_process_incoming, s,			     SIPTAG_CALL_ID(sip->sip_call_id),			     SIPTAG_FROM(sip->sip_to), /* local address */			     SIPTAG_TO(sip->sip_from), /* remote address */			     URLTAG_URL(target),			     TAG_END());  if (s->s_local && s->s_leg) {    nta_leg_tag(s->s_leg, NULL);    return 0;  }  else {    nea_sub_destroy(s);    return -1;  }}#endifstaticint nea_server_callback(nea_sub_t *nes_as_sub,			nta_leg_t *leg,			nta_incoming_t *irq, 			sip_t const *sip){  return nea_server_add_irq((nea_server_t *)nes_as_sub, leg, NULL, irq, sip);}/** Process incoming request */int nea_server_add_irq(nea_server_t *nes,		       nta_leg_t *leg,		       sip_contact_t const *local_target,		       nta_incoming_t *irq, 		       sip_t const *sip){  nea_sub_t *s = NULL;  s = nea_sub_create(nes);  s->s_from = sip_from_dup(nes->nes_home, sip->sip_from);  if (local_target == NULL)    local_target = nes->nes_eventity_uri;  s->s_local = sip_contact_dup(nes->nes_home, local_target);  if (leg == NULL || leg == nes->nes_leg) {    url_t target[1];        *target = *local_target->m_url;    s->s_leg = nta_leg_tcreate(nes->nes_agent, nea_sub_process_incoming, s, 			       SIPTAG_FROM(sip->sip_to),			       SIPTAG_TO(sip->sip_from),			       SIPTAG_CALL_ID(sip->sip_call_id),			       URLTAG_URL((url_string_t *)target),			       TAG_NULL());  }  else {    nta_leg_bind(s->s_leg = leg, nea_sub_process_incoming, s);  }    if (s->s_leg) {    if (sip->sip_to->a_tag == NULL) {      nta_leg_tag(s->s_leg, NULL);      nta_incoming_tag(irq, nta_leg_get_tag(s->s_leg));    }    nta_leg_server_route(s->s_leg, sip->sip_record_route, sip->sip_contact);    return nea_sub_process_incoming(s, s->s_leg, irq, sip);  }  else {    nea_sub_destroy(s);    return 500;  }}/* ----------------------------------------------------------------- *//**Process incoming transactions for event dialog. * * The nea_sub_process_incoming() processes the transactions for event * dialog. Currently, no other methods allowed beside SUBSCRIBE. The * SUBSCRIBE is processed by nea_sub_process_subscribe(). * * @param s   pointer to subscriber object * @param leg pointer to NTA dialog object * @param irq pointer to NTA server transaction * @param sip pointer to structure containing SIP headers of the request * * The nea_sub_process_incoming() returns 0 if successful, SIP error code * otherwise. */int nea_sub_process_incoming(nea_sub_t *s,			     nta_leg_t *leg,			     nta_incoming_t *irq,			     sip_t const *sip){  int retval;  s->s_processing = 1;  s->s_irq = irq;  switch(sip->sip_request->rq_method) {  case sip_method_subscribe:    retval = nea_sub_process_subscribe(s, leg, irq, sip);    break;  default:    nta_incoming_treply(irq, 			retval = SIP_405_METHOD_NOT_ALLOWED,			SIPTAG_ALLOW_STR("SUBSCRIBE"),			TAG_END());    retval = 405;  }  s->s_processing = 0;  if (s->s_irq)    nta_incoming_destroy(irq), s->s_irq = NULL;    if (s->s_pending_flush || s->s_state == nea_embryonic)    nea_sub_destroy(s);  return retval;}/* ----------------------------------------------------------------- *//**Process incoming SUBSCRIBE transactions for event dialog. * * The function nea_sub_process_subscribe() processes the SUBSCRIBE * transactions for (possible) event dialog. * * @param s   pointer to subscriber object * @param leg pointer to NTA dialog object * @param irq pointer to NTA server transaction * @param sip pointer to structure containing SIP headers of the request * * @return * The function nea_sub_process_subscribe() returns 0 if successful, and a * SIP error code otherwise. */int nea_sub_process_subscribe(nea_sub_t *s,			      nta_leg_t *leg,			      nta_incoming_t *irq,			      sip_t const *sip){  nea_server_t *nes = s->s_nes;  su_home_t *home = nes->nes_home;  nea_event_t *ev = NULL, *ev_maybe = NULL;  nea_event_view_t *evv = NULL, *evv_maybe = NULL;  sip_time_t delta = 0, now = sip_now();  sip_expires_t expires[1] = { SIP_EXPIRES_INIT() };  sip_unsupported_t *unsupported;  sip_event_t const *o;  sip_accept_t const *ac = NULL, *accept = NULL;  sip_accept_t *a0 = NULL, *a, *a_next, **aa;  sip_accept_t accept_default[1];  unsigned proposed_throttle;  char const *type, *throttle;  int once, what, supported_eventlist, require_eventlist;  if (sip->sip_payload && !sip->sip_content_type) {    nta_incoming_treply(irq, 400, "Missing Content-Type", 			SIPTAG_SERVER_STR(nes->nes_server),			SIPTAG_ALLOW_EVENTS(nes->nes_allow_events),			SIPTAG_ALLOW(nes->nes_allow_methods),			TAG_NULL());    return 0;  }  if (sip->sip_expires &&       sip->sip_expires->ex_delta > 0 &&       sip->sip_expires->ex_delta < nes->nes_min_expires) {    sip_min_expires_t me[1];     sip_min_expires_init(me);    me->me_delta = nes->nes_min_expires;    nta_incoming_treply(irq, 423, "Subscription Interval Too Small", 			SIPTAG_ACCEPT(accept),			SIPTAG_MIN_EXPIRES(me),			SIPTAG_SERVER_STR(nes->nes_server),			SIPTAG_ALLOW_EVENTS(nes->nes_allow_events),			SIPTAG_ALLOW(nes->nes_allow_methods),			TAG_NULL());    return 0;  }  /* Check features */  if (nes->nes_require) {    unsupported = sip_has_unsupported2(nes->nes_home, 				       sip->sip_supported,				       sip->sip_require,				       nes->nes_require);    if (unsupported) {      nta_incoming_treply(irq, SIP_421_EXTENSION_REQUIRED, 			  SIPTAG_REQUIRE(nes->nes_require),			  SIPTAG_UNSUPPORTED(unsupported),			  SIPTAG_SERVER_STR(nes->nes_server),			  SIPTAG_ALLOW_EVENTS(nes->nes_allow_events),			  SIPTAG_ALLOW(nes->nes_allow_methods),			  TAG_NULL());      su_free(nes->nes_home, unsupported);      return 0;    }  }  supported_eventlist = sip_has_feature(sip->sip_supported, "eventlist");  require_eventlist = sip_has_feature(sip->sip_require, "eventlist");  supported_eventlist = supported_eventlist || require_eventlist;  if (s->s_id && (!sip->sip_event || 		  str0cmp(s->s_id->o_type, sip->sip_event->o_type) != 0 ||		  str0cmp(s->s_id->o_id, sip->sip_event->o_id))) {    /* Multiple subscriptions per dialog are not supported. */    return nta_incoming_treply(irq, 501, 			       "Multiple subscriptions not implemented", 			       SIPTAG_SERVER_STR(nes->nes_server),			       TAG_NULL());  }  /* Check that subscriber asks for a supported event  */  for (once = 0; ev == NULL ;once++) {    o = sip->sip_event;    /* Check that we have a matching event */    if (o && o->o_type) {      for (ev = nes->nes_events; ev; ev = ev->ev_next) {	if (strcmp(o->o_type, ev->ev_event->o_type) == 0) {	  ev_maybe = ev;	  if (ev->ev_eventlist) {	    if (supported_eventlist)	      break;	  } else {	    if (!supported_eventlist)	      break;	  }	}      }    }    if (!ev && !require_eventlist)      ev = ev_maybe;              if (ev || once)      break;    /* Ask the application either to       1) add a new event or assing us an event/payload (0),        2) take care of transaction (positive), or        3) drop request (negative).    */    if ((what = nes_new_event_callback(nes, &ev, &evv, irq, sip)) < 0)      break;    if (what > 0) {      s->s_irq = NULL;      return 0;    }  }  if (ev_maybe == NULL && ev == NULL) {    nta_incoming_treply(irq, SIP_489_BAD_EVENT, 			SIPTAG_SERVER_STR(nes->nes_server),			SIPTAG_ALLOW_EVENTS(nes->nes_allow_events),			SIPTAG_ALLOW(nes->nes_allow_methods),			NULL);    return 0;  } else if (ev == NULL) {    ev = ev_maybe;    unsupported = sip_has_unsupported(nes->nes_home, ev->ev_supported,				      sip->sip_require);    nta_incoming_treply(irq, SIP_420_BAD_EXTENSION, 			SIPTAG_UNSUPPORTED(unsupported),			SIPTAG_REQUIRE(ev->ev_require),			SIPTAG_SUPPORTED(ev->ev_supported),			SIPTAG_SERVER_STR(nes->nes_server),			SIPTAG_ALLOW_EVENTS(nes->nes_allow_events),			SIPTAG_ALLOW(nes->nes_allow_methods),			TAG_NULL());    su_free(nes->nes_home, unsupported);    return 0;  }  if (sip->sip_accept)    accept = sip->sip_accept;  else if (evv && evv->evv_content_type) {    /* Generate accept header from event view specified by application */    sip_accept_init(accept_default);    accept_default->ac_type = evv->evv_content_type->c_type;    accept_default->ac_subtype = evv->evv_content_type->c_subtype;    accept = a0;  }  else    accept = ev->ev_default;  for (once = 0; evv == NULL ;once++) {    /* If there are multiple accept values with different Q values,       insertion sort by Q value */    for (ac = accept->ac_next; ac; ac = ac->ac_next) {      if (ac->ac_q != accept->ac_q) {	if ((a0 = sip_accept_dup(home, accept))) {	  /* Sort the accept list by Q values */	  for (a = a0, accept = NULL; a; a = a_next) {	    a_next = a->ac_next;	    	    for (aa = (sip_accept_t **)&accept; 		 *aa && sip_q_value((*aa)->ac_q) >= sip_q_value(a->ac_q); 		 aa = &(*aa)->ac_next)	      ;	    	    a->ac_next = *aa; *aa = a; 	/* Insert */	  }	}	break;      }    }    /* Check that subscriber asks for a supported content type */    for (ac = accept; ac; ac = ac->ac_next) {      int i;      if (ac->ac_type == NULL || ac->ac_subtype == NULL)	continue;            /* Check all supported content types v. accept */      for (i = 0; (evv = ev->ev_views[i]); i++) {	assert(evv->evv_content_type && evv->evv_content_type->c_type);		if (strcmp(ac->ac_type, "*/*") == 0)	  break;	type = evv->evv_content_type->c_type;	if ((strcasecmp(ac->ac_type, type) == 0) ||	    (strcasecmp(ac->ac_subtype, "*") == 0 &&	     strncasecmp(ac->ac_type, type, 			 ac->ac_subtype - ac->ac_type) == 0)) {	  if (evv_maybe == NULL)	    evv_maybe = evv;	}      }      if (evv)			/* Found */	break;    }    /* Free the sorted Accept list */    for (a = a0; a; a = a_next)      a_next = a->ac_next, su_free(home, a);     if (!evv)      evv = evv_maybe;      if (evv || once)      break;    /* Ask the application either to       1) add a new event view or assign us an event view (0),        2) take care of transaction (positive), or        3) drop request (negative).    */    if ((what = nes_new_event_callback(nes, &ev, &evv, irq, sip)) < 0)      break;    if (what > 0) {      s->s_irq = NULL;      return 0;    }  }  if (evv == NULL) {    SU_DEBUG_3(("nea_server: event %s rejected %u %s\n",		ev->ev_event->o_type, SIP_406_NOT_ACCEPTABLE));    /* There is no media acceptable to watcher */    return nta_incoming_treply(irq, SIP_406_NOT_ACCEPTABLE, 			       SIPTAG_ACCEPT(ev->ev_accept),			       SIPTAG_SERVER_STR(nes->nes_server),			       SIPTAG_ALLOW_EVENTS(nes->nes_allow_events),			       SIPTAG_ALLOW(nes->nes_allow_methods),			       TAG_NULL());  }  /* Do not change private view */  if (s->s_view && s->s_view->evv_primary == evv)    evv = s->s_view;  /* Set throttle */  if (sip->sip_event &&       (throttle = sip_params_find(sip->sip_event->o_params, "throttle="))) {    proposed_throttle = strtoul(throttle, NULL, 10);    if (proposed_throttle < evv->evv_min_throttle)      proposed_throttle = evv->evv_min_throttle;  } else    proposed_throttle = evv->evv_throttle;  s->s_throttle = proposed_throttle;  /* Update route, store remote contact */  nta_leg_server_route(leg, sip->sip_record_route, sip->sip_contact);  su_free(home, s->s_remote);  s->s_remote = sip_contact_dup(home, sip->sip_contact);  /* Store content-type and body */  if (sip->sip_content_type) {    su_free(home, s->s_content_type);    s->s_content_type = sip_content_type_dup(home, sip->sip_content_type);    su_free(home, s->s_payload);    s->s_payload = sip_payload_dup(home, sip->sip_payload);  }  /* Calculate expiration time for subscription */  delta = sip_contact_expires(NULL, sip->sip_expires, sip->sip_date,			      nes->nes_expires, now);  if (delta > nes->nes_max_expires)    delta = nes->nes_max_expires;  expires->ex_delta = delta;  if (s->s_subscribed == 0)    s->s_subscribed = now;  s->s_expires = now + delta;  /* s->s_accept = sip_accept_dup(home, accept); */  if (s->s_id == NULL)    s->s_id = sip_event_dup(home, sip->sip_event);  s->s_event = ev;  s->s_eventlist = supported_eventlist;  nea_sub_assign_view(s, evv);  s->s_updated = evv->evv_updated - 1;  /* Force notify */  if (nes->nes_202_before_notify) {    nta_incoming_treply(irq, SIP_202_ACCEPTED, 			SIPTAG_SERVER_STR(nes->nes_server),			SIPTAG_ALLOW_EVENTS(nes->nes_allow_events),			SIPTAG_ALLOW(nes->nes_allow_methods),

⌨️ 快捷键说明

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