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

📄 nta.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
    agent_set_params(agent, ta_args(ta));    if (agent->sa_mclass == NULL)      agent->sa_mclass = sip_default_mclass();    agent->sa_in.re_t1 = &agent->sa_in.re_list;        incoming_queue_init(agent->sa_in.proceeding, 0);    incoming_queue_init(agent->sa_in.preliminary, agent->sa_t1x64); /* P1 */    incoming_queue_init(agent->sa_in.inv_completed, agent->sa_t1x64); /* H */    incoming_queue_init(agent->sa_in.inv_confirmed, agent->sa_t4); /* I */    incoming_queue_init(agent->sa_in.completed, agent->sa_t1x64); /* J */    incoming_queue_init(agent->sa_in.terminated, 0);    incoming_queue_init(agent->sa_in.final_failed, 0);     agent->sa_out.re_t1 = &agent->sa_out.re_list;    outgoing_queue_init(agent->sa_out.delayed, 0);    outgoing_queue_init(agent->sa_out.resolving, 0);    outgoing_queue_init(agent->sa_out.trying, agent->sa_t1x64); /* F */    outgoing_queue_init(agent->sa_out.completed, agent->sa_t4); /* K */    outgoing_queue_init(agent->sa_out.terminated, 0);     /* Special queues (states) for outgoing INVITE transactions */    outgoing_queue_init(agent->sa_out.inv_calling, agent->sa_t1x64); /* B */    timer_c = (agent->sa_use_timer_c || !agent->sa_is_a_uas)      ? agent->sa_timer_c : 0;    outgoing_queue_init(agent->sa_out.inv_proceeding, timer_c); /* C */    outgoing_queue_init(agent->sa_out.inv_completed, 32000); /* Timer D */    if (leg_htable_resize(agent->sa_home, agent->sa_dialogs, 0) < 0 ||	leg_htable_resize(agent->sa_home, agent->sa_defaults, 0) < 0 ||	outgoing_htable_resize(agent->sa_home, agent->sa_outgoing, 0) < 0 ||	incoming_htable_resize(agent->sa_home, agent->sa_incoming, 0) < 0) {      SU_DEBUG_0(("nta_agent_create: failure with %s\n", "hash tables"));      goto deinit;    }    SU_DEBUG_9(("nta_agent_create: initialized %s\n", "hash tables"));    if (contact_url != (url_string_t *)-1 &&	nta_agent_add_tport(agent, contact_url, ta_tags(ta)) < 0) {      SU_DEBUG_7(("nta_agent_create: failure with %s\n", "transport"));      goto deinit;    }    SU_DEBUG_9(("nta_agent_create: initialized %s\n", "transports"));    if (agent_tag_init(agent) < 0) {      SU_DEBUG_3(("nta_agent_create: failure with %s\n", "random identifiers"));      goto deinit;    }    SU_DEBUG_9(("nta_agent_create: initialized %s\n", "random identifiers"));    if (agent_timer_init(agent) < 0) {      SU_DEBUG_0(("nta_agent_create: failure with %s\n", "timer"));      goto deinit;    }    SU_DEBUG_9(("nta_agent_create: initialized %s\n", "timer"));    if (agent_launch_terminator(agent) == 0)      SU_DEBUG_9(("nta_agent_create: initialized %s\n", "threads"));#if HAVE_SOFIA_SRESOLV    agent->sa_resolver = sres_resolver_create(root, NULL, ta_tags(ta));    if (!agent->sa_resolver) {      SU_DEBUG_0(("nta_agent_create: failure with %s\n", "resolver"));    }    SU_DEBUG_9(("nta_agent_create: initialized %s\n", "resolver"));#endif    ta_end(ta);    return agent;  deinit:    nta_agent_destroy(agent);  }  ta_end(ta);  return NULL;}/** * Destroy an NTA agent object. * * @param agent the NTA agent object to be destroyed. * */void nta_agent_destroy(nta_agent_t *agent){  if (agent) {    size_t i;    outgoing_htable_t *oht = agent->sa_outgoing;    incoming_htable_t *iht = agent->sa_incoming;    /* Currently, this is pretty pointless, as legs don't keep any resources */    leg_htable_t *lht;    nta_leg_t *leg;    for (i = 0, lht = agent->sa_dialogs; i < lht->lht_size; i++) {      if ((leg = lht->lht_table[i])) {	SU_DEBUG_3(("nta_agent_destroy: destroying dialog with <"		    URL_PRINT_FORMAT ">\n",		    URL_PRINT_ARGS(leg->leg_remote->a_url)));	leg_free(agent, leg);      }    }    for (i = 0, lht = agent->sa_defaults; i < lht->lht_size; i++) {      if ((leg = lht->lht_table[i])) {	SU_DEBUG_3(("%s: destroying leg for <" 		    URL_PRINT_FORMAT ">\n",		    __func__, URL_PRINT_ARGS(leg->leg_url)));	leg_free(agent, leg);      }    }    if (agent->sa_default_leg)      leg_free(agent, agent->sa_default_leg);    for (i = iht->iht_size; i-- > 0; )      while (iht->iht_table[i]) {	nta_incoming_t *irq = iht->iht_table[i];	if (!irq->irq_destroyed)	  SU_DEBUG_3(("%s: destroying %s server transaction from <"		      URL_PRINT_FORMAT ">\n",		      __func__, irq->irq_rq->rq_method_name,		      URL_PRINT_ARGS(irq->irq_from->a_url)));	incoming_free(irq);      }    for (i = oht->oht_size; i-- > 0;)      while (oht->oht_table[i]) {	nta_outgoing_t *orq = oht->oht_table[i];	if (!orq->orq_destroyed)	  SU_DEBUG_3(("%s: destroying %s client transaction to <"		      URL_PRINT_FORMAT ">\n",		      __func__, orq->orq_method_name,		      URL_PRINT_ARGS(orq->orq_to->a_url)));	outgoing_free(orq);      }    su_timer_destroy(agent->sa_timer), agent->sa_timer = NULL;#   if HAVE_SOFIA_SRESOLV    sres_resolver_destroy(agent->sa_resolver), agent->sa_resolver = NULL;#   endif    tport_destroy(agent->sa_tports), agent->sa_tports = NULL;    agent_kill_terminator(agent);    su_home_unref(agent->sa_home);  }}/** Return agent context. */nta_agent_magic_t *nta_agent_magic(nta_agent_t const *agent){  return agent ? agent->sa_magic : NULL;}/** Return @Contact header. * * Get a @Contact header, which can be used to reach @a agent. * * @param agent NTA agent object * * User agents can insert the @Contact header in the outgoing REGISTER, * INVITE, and ACK requests and replies to incoming INVITE and OPTIONS * transactions. * * Proxies can use the @Contact header to create appropriate @RecordRoute * headers: * @code * r_r = sip_record_route_create(msg_home(msg), *	 			 sip->sip_request->rq_url, *				 contact->m_url); * @endcode * * @return A sip_contact_t object corresponding to the @a agent. */sip_contact_t *nta_agent_contact(nta_agent_t const *agent){  return agent ? agent->sa_contact : NULL;}/** Return a list of @Via headers. * * Get @Via headers for all activated transport. * * @param agent NTA agent object * * @return A list of #sip_via_t objects used by the @a agent. */sip_via_t *nta_agent_via(nta_agent_t const *agent){  return agent ? agent->sa_vias : NULL;}/** Return a list of public (UPnP, STUN) @Via headers. * * Get public @Via headers for all activated transports. * * @param agent NTA agent object * * @return A list of #sip_via_t objects used by the @a agent. */sip_via_t *nta_agent_public_via(nta_agent_t const *agent){  return agent ? agent->sa_public_vias : NULL;}/** Match a @Via header @a v with @Via headers in @a agent. * */staticsip_via_t *agent_has_via(nta_agent_t const *agent, sip_via_t const *via){  sip_via_t const *v;  for (v = agent->sa_public_vias; v; v = v->v_next) {    if (strcasecmp(via->v_host, v->v_host))      continue;    if (str0cmp(via->v_port, v->v_port))      continue;    if (strcasecmp(via->v_protocol, v->v_protocol))      continue;    return (sip_via_t *)v;  }  for (v = agent->sa_vias; v; v = v->v_next) {    if (strcasecmp(via->v_host, v->v_host))      continue;    if (str0cmp(via->v_port, v->v_port))      continue;    if (strcasecmp(via->v_protocol, v->v_protocol))      continue;    return (sip_via_t *)v;  }  return NULL;}/** Return @UserAgent header. * * Get @UserAgent information with NTA version. * * @param agent NTA agent object (may be NULL) * * @return A string containing the @a agent version. */char const *nta_agent_version(nta_agent_t const *agent){  return "nta" "/" VERSION;}/** Initialize default tag */static int agent_tag_init(nta_agent_t *self){  sip_contact_t *m = self->sa_contact;  uint32_t hash = 1;  if (m) {    if (m->m_url->url_user)      hash = 914715421U * hash + msg_hash_string(m->m_url->url_user);    if (m->m_url->url_host)      hash = 914715421U * hash + msg_hash_string(m->m_url->url_host);    if (m->m_url->url_port)      hash = 914715421U * hash + msg_hash_string(m->m_url->url_port);    if (m->m_url->url_params)      hash = 914715421U * hash + msg_hash_string(m->m_url->url_params);  }  if (hash == 0)    hash = 914715421U;  self->sa_branch = NTA_BRANCH_PRIME * su_ntp_now();  self->sa_branch *= hash;  self->sa_tags = NTA_TAG_PRIME * self->sa_branch;  return 0;}/** Initialize agent timer. */staticint agent_timer_init(nta_agent_t *agent){  agent->sa_timer = su_timer_create(su_root_task(agent->sa_root),				    NTA_SIP_T1 / 8);#if 0  return su_timer_set(agent->sa_timer,		      agent_timer,		      agent);#endif  return -(agent->sa_timer == NULL);}/** * Agent timer routine. */staticvoid agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent){  su_time_t stamp = su_now();  uint32_t now = su_time_ms(stamp), next, latest;  now += now == 0;  agent->sa_next = 0;  agent->sa_now = stamp;  agent->sa_millisec = now;  agent->sa_in_timer = 1;  outgoing_timer(agent);  incoming_timer(agent);  /* agent->sa_now is used only if sa_millisec != 0 */  agent->sa_millisec = 0;  agent->sa_in_timer = 0;  /* Calculate next timeout */  next = latest = now + NTA_TIME_MAX + 1;#define NEXT_TIMEOUT(next, p, f, now) \  (void)(p && (int32_t)(p->f - (next)) < 0 && \	 ((next) = ((int32_t)(p->f - (now)) > 0 ? p->f : (now))))  NEXT_TIMEOUT(next, agent->sa_out.re_list, orq_retry, now);  NEXT_TIMEOUT(next, agent->sa_out.inv_completed->q_head, orq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_out.completed->q_head, orq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_out.inv_calling->q_head, orq_timeout, now);  if (agent->sa_out.inv_proceeding->q_timeout)    NEXT_TIMEOUT(next, agent->sa_out.inv_proceeding->q_head, orq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_out.trying->q_head, orq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_in.preliminary->q_head, irq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_in.inv_completed->q_head, irq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_in.inv_confirmed->q_head, irq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_in.completed->q_head, irq_timeout, now);  NEXT_TIMEOUT(next, agent->sa_in.re_list, irq_retry, now);  if (agent->sa_next)    NEXT_TIMEOUT(next, agent, sa_next, now);#undef NEXT_TIMEOUT  if (next == latest) {    /* Do not set timer? */    SU_DEBUG_9(("nta: timer not set\n"));    assert(!agent->sa_out.completed->q_head);    assert(!agent->sa_out.trying->q_head);    assert(!agent->sa_out.inv_calling->q_head);    assert(!agent->sa_out.re_list);    assert(!agent->sa_in.inv_confirmed->q_head);    assert(!agent->sa_in.preliminary->q_head);    assert(!agent->sa_in.completed->q_head);    assert(!agent->sa_in.inv_completed->q_head);    assert(!agent->sa_in.re_list);    return;  }  if (next == now) if (++next == 0) ++next;  SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set next", (long)(next - now)));  agent->sa_next = next;  su_timer_set_at(timer, agent_timer, agent, su_time_add(stamp, next - now));}/** Add uin32_t milliseconds to the time. */static su_time_t add_milliseconds(su_time_t t0, uint32_t ms){  unsigned long sec = ms / 1000, usec = (ms % 1000) * 1000;  t0.tv_usec += usec;  t0.tv_sec += sec;  if (t0.tv_usec >= 1000000) {    t0.tv_sec += 1;    t0.tv_usec -= 1000000;  }  return t0;}/** Calculate nonzero value for timeout. * * Sets or adjusts agent timer when needed. * * @retval 0 if offset is 0 * @retval timeout (millisecond counter) otherwise */staticuint32_t set_timeout(nta_agent_t *agent, uint32_t offset){  su_time_t now;  uint32_t next, ms;  if (offset == 0)    return 0;  if (agent->sa_millisec) /* Avoid expensive call to su_now() */    now = agent->sa_now, ms = agent->sa_millisec;  else    now = su_now(), ms = su_time_ms(now);    next = ms + offset; if (next == 0) next = 1;  if (agent->sa_in_timer)	/* Currently executing timer */    return next;  if (agent->sa_next == 0 || (int32_t)(agent->sa_next - next - 5L) > 0) {    /* Set timer */    if (agent->sa_next)      SU_DEBUG_9(("nta: timer %s to %ld ms\n", "shortened", (long)offset));    else      SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set", (long)offset));          su_timer_set_at(agent->sa_timer, agent_timer, agent, 		    add_milliseconds(now, offset));    agent->sa_next = next;  }  return next;

⌨️ 快捷键说明

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