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

📄 nta.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@CFILE nta.c * @brief Sofia SIP Transaction API implementation *  * This source file has been divided into sections as follows: * 1) agent * 2) tport handling * 3) dispatching messages received from network * 4) message creation, message utility * 5) stateless operation * 6) dialogs (legs) * 7) server transactions (incoming) * 8) client transactions (outgoing) * 9) resolving URLs for client transactions * 10) 100rel reliable responses (reliable) * 11) SigComp handling and public transport interface *  * @author Pekka Pessi <Pekka.Pessi@nokia.com> *  * @date Created: Tue Jun 13 02:57:51 2000 ppessi */#include "config.h"#include <sofia-sip/string0.h>/** @internal SU message argument structure type */#define SU_MSG_ARG_T   union sm_arg_u/** @internal SU timer argument pointer type */#define SU_TIMER_ARG_T struct nta_agent_s#include <sofia-sip/su_alloc.h>#include <sofia-sip/su.h>#include <sofia-sip/su_time.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/base64.h>#include <sofia-sip/su_uniqueid.h>#include <sofia-sip/sip.h>#include <sofia-sip/sip_header.h>#include <sofia-sip/sip_util.h>#include <sofia-sip/sip_status.h>#include <sofia-sip/msg_addr.h>#include "nta_internal.h"#include "sofia-sip/nta_stateless.h"#include "sofia-sip/url_tag.h"#if !defined(random) && defined(_WIN32)#define random rand#endif#if !defined(EMSGSIZE) && defined(_WIN32)#define EMSGSIZE WSAEMSGSIZE#endif#include <stddef.h>#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <assert.h>#include <limits.h>#include <errno.h>/* From AM_INIT/AC_INIT in our "config.h" */char const nta_version[] = PACKAGE_VERSION;#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#elsestatic char const __func__[] = "nta";#endif#define NONE ((void *)-1)/* Internal tags *//* Delay sending of request */#define NTATAG_DELAY_SENDING(x) ntatag_delay_sending, tag_bool_v((x))#define NTATAG_DELAY_SENDING_REF(x) \ntatag_delay_sending_ref, tag_bool_vr(&(x))extern tag_typedef_t ntatag_delay_sending;extern tag_typedef_t ntatag_delay_sending_ref;/* Allow sending incomplete responses */#define NTATAG_INCOMPLETE(x) ntatag_incomplete, tag_bool_v((x))#define NTATAG_INCOMPLETE_REF(x) \ntatag_incomplete_ref, tag_bool_vr(&(x))extern tag_typedef_t ntatag_incomplete;extern tag_typedef_t ntatag_incomplete_ref;nta_compressor_vtable_t *nta_compressor_vtable = NULL;/* Agent */static int agent_tag_init(nta_agent_t *self);static int agent_timer_init(nta_agent_t *agent);static void agent_timer(su_root_magic_t *rm, su_timer_t *, nta_agent_t *);static int agent_launch_terminator(nta_agent_t *agent);static void agent_kill_terminator(nta_agent_t *agent);static int agent_set_params(nta_agent_t *agent, tagi_t *tags);static void agent_set_udp_params(nta_agent_t *self, unsigned udp_mtu);static int agent_get_params(nta_agent_t *agent, tagi_t *tags);/* Transport interface */static sip_via_t const *agent_tport_via(tport_t *tport);static int outgoing_insert_via(nta_outgoing_t *orq, sip_via_t const *);static int nta_tpn_by_via(tp_name_t *tpn, sip_via_t const *v, int *using_rport);static msg_t *nta_msg_create_for_transport(nta_agent_t *agent, int flags,					   char const data[], unsigned dlen);static int complete_response(msg_t *response, 			     int status, char const *phrase, 			     msg_t const *request);#define IF_SIGCOMP_TPTAG_COMPARTMENT(cc)     TAG_IF(cc, TPTAG_COMPARTMENT(cc)),#define IF_SIGCOMP_TPTAG_COMPARTMENT_REF(cc) TPTAG_COMPARTMENT_REF(cc),struct sigcomp_compartment;struct sigcomp_compartment *nta_compartment_ref(struct sigcomp_compartment *cc);staticstruct sigcomp_compartment *agent_compression_compartment(nta_agent_t *sa, tport_t *tp, tp_name_t const *tpn,			      int new_if_needed);staticint agent_accept_compressed(nta_agent_t *sa, msg_t *msg,			    struct sigcomp_compartment *cc);static int agent_close_compressor(nta_agent_t *sa,				  struct sigcomp_compartment *cc);static int agent_zap_compressor(nta_agent_t *sa,				struct sigcomp_compartment *cc);static char const * stateful_branch(su_home_t *home, nta_agent_t *);static char const * stateless_branch(nta_agent_t *, msg_t *, sip_t const *,				    tp_name_t const *tp);#define NTA_BRANCH_PRIME SU_U64_C(0xB9591D1C361C6521)#define NTA_TAG_PRIME    SU_U64_C(0xB9591D1C361C6521)HTABLE_PROTOS(leg_htable, lht, nta_leg_t);static nta_leg_t *leg_find(nta_agent_t const *sa,			   char const *method_name,			   url_t const *request_uri,			   sip_call_id_t const *i,			   char const *from_tag,			   url_t const *from_uri,			   char const *to_tag,			   url_t const *to_uri);static nta_leg_t *dst_find(nta_agent_t const *sa, url_t const *u0,			   char const *method);static void leg_recv(nta_leg_t *, msg_t *, sip_t *, tport_t *);static void leg_free(nta_agent_t *sa, nta_leg_t *leg);#define NTA_HASH(i, cs) ((i)->i_hash + 26839U * (uint32_t)(cs))HTABLE_PROTOS(incoming_htable, iht, nta_incoming_t);static nta_incoming_t *incoming_create(nta_agent_t *agent,				       msg_t *request,				       sip_t *sip,				       tport_t *tport,				       char const *tag);static int incoming_callback(nta_leg_t *leg, nta_incoming_t *irq, sip_t *sip);static void incoming_free(nta_incoming_t *irq);static inline void incoming_cut_off(nta_incoming_t *irq);static inline void incoming_reclaim(nta_incoming_t *irq);static void incoming_queue_init(incoming_queue_t *, 				unsigned timeout);static void incoming_queue_adjust(nta_agent_t *sa, 				  incoming_queue_t *queue, 				  unsigned timeout);static inlinenta_incoming_t *incoming_find(nta_agent_t const *agent, sip_t const *sip,			      sip_via_t const *v,			      nta_incoming_t **merge,			      nta_incoming_t **ack);static int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip);static inline int incoming_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip,				tport_t *tport);static inline int incoming_ack(nta_incoming_t *irq, msg_t *msg, sip_t *sip,			       tport_t *tport);static inline int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip,				  tport_t *tport);static inline int incoming_merge(nta_incoming_t *irq, msg_t *msg, sip_t *sip,				 tport_t *tport);static inline int incoming_timestamp(nta_incoming_t *, msg_t *, sip_t *);static inline int incoming_timer(nta_agent_t *, su_duration_t);static nta_reliable_t *reliable_mreply(nta_incoming_t *,				       nta_prack_f *, nta_reliable_magic_t *,				       msg_t *, sip_t *);static int reliable_send(nta_incoming_t *, nta_reliable_t *, msg_t *, sip_t *);static int reliable_final(nta_incoming_t *irq, msg_t *msg, sip_t *sip);static msg_t *reliable_response(nta_incoming_t *irq);static int reliable_recv(nta_incoming_t *, msg_t *, sip_t *, tport_t *);static void reliable_flush(nta_incoming_t *irq);static void reliable_timeout(nta_incoming_t *irq, int timeout);HTABLE_PROTOS(outgoing_htable, oht, nta_outgoing_t);static nta_outgoing_t *outgoing_create(nta_agent_t *agent,				       nta_response_f *callback,				       nta_outgoing_magic_t *magic,				       url_string_t const *route_url,				       tp_name_t const *tpn,				       msg_t *msg,				       tag_type_t tag, tag_value_t value, ...);static void outgoing_queue_init(outgoing_queue_t *, 				unsigned timeout);static void outgoing_queue_adjust(nta_agent_t *sa, 				  outgoing_queue_t *queue, 				  unsigned timeout);static void outgoing_free(nta_outgoing_t *orq);static inline void outgoing_cut_off(nta_outgoing_t *orq);static inline void outgoing_reclaim(nta_outgoing_t *orq);static nta_outgoing_t *outgoing_find(nta_agent_t const *sa,				     msg_t const *msg,				     sip_t const *sip,				     sip_via_t const *v);static int outgoing_recv(nta_outgoing_t *orq, int status, msg_t *, sip_t *);static void outgoing_default_recv(nta_outgoing_t *, int, msg_t *, sip_t *);static inline int outgoing_timer(nta_agent_t *, su_duration_t);static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip);/* Internal message passing */union sm_arg_u {  struct leg_recv_s {    nta_leg_t    *leg;    msg_t        *msg;    tport_t      *tport;  } a_leg_recv[1];  struct outgoing_recv_s {    nta_outgoing_t *orq;    msg_t          *msg;    sip_t          *sip;    int             status;  } a_outgoing_recv[1];  incoming_queue_t a_incoming_queue[1];  outgoing_queue_t a_outgoing_queue[1];};/* Global module data *//**@var NTA_DEBUG * * Environment variable determining the default debug log level. * * The NTA_DEBUG environment variable is used to determine the default * debug logging level. The normal level is 3. *  * @sa <su_debug.h>, su_log_global, SOFIA_DEBUG */extern char const NTA_DEBUG[];#ifndef SU_DEBUG#define SU_DEBUG 3#endif/**Debug log for @b nta module.  *  * The nta_log is the log object used by @b nta module. The level of * #nta_log is set using #NTA_DEBUG environment variable. */su_log_t nta_log[] = { SU_LOG_INIT("nta", "NTA_DEBUG", SU_DEBUG) };/* ====================================================================== *//* 1) Agent *//** * Create an NTA agent object. * * The function nta_agent_create() creates an NTA agent object.  The agent * object creates and binds a server socket with address specified in @e url. * If the @e host portion of the @e url is @c "*", the agent listens to all * addresses available on the host. * * When a message is received, the agent object parses it.  If the result is * a valid SIP message, the agent object passes the message to the * application by invoking the nta_message_f @e callback function. * * @note * The @e url can be either parsed url (of type url_t ()), or a valid * SIP URL as a string. * * @note * If @e url is @c NULL, the default @e url @c "sip:*" is used. * @par * If @p transport parameters are specified in @a url, agent uses only * specified transport type. * * @par * If an @p maddr parameter is specified in @e url, agent binds to the * specified address, but uses @e host part of @e url in @b Contact and @b * Via headers.  The @p maddr parameter is also included, unless it equals * to @c INADDR_ANY (@p 0.0.0.0 or @p [::]). * * @param root          pointer to a su_root_t used for synchronization * @param contact_url   URL that agent uses to bind the server sockets * @param callback      pointer to callback function * @param magic         pointer to user data * @param tag,value,... other arguments * * @note It is possible to provide -1 as @a contact_url. *  * @retval handle to the agent when successful, * @retval NULL upon an error. * */nta_agent_t *nta_agent_create(su_root_t *root,			      url_string_t const *contact_url,			      nta_message_f *callback,			      nta_agent_magic_t *magic,			      tag_type_t tag, tag_value_t value, ...){  nta_agent_t *agent;  ta_list ta;  if (root == NULL)    return su_seterrno(EINVAL), NULL;  ta_start(ta, tag, value);  if ((agent = su_home_new(sizeof(*agent)))) {    agent->sa_root = root;    agent->sa_callback = callback;    agent->sa_magic = magic;    agent->sa_flags = MSG_DO_CANONIC;    agent->sa_maxsize         = 2 * 1024 * 1024;    agent->sa_t1 	      = NTA_SIP_T1;    agent->sa_t2 	      = NTA_SIP_T2;    agent->sa_t4              = NTA_SIP_T4;    agent->sa_t1x64 	      = 64 * NTA_SIP_T1;    agent->sa_drop_prob       = 0;    agent->sa_is_a_uas        = 0;    agent->sa_progress        = 60 * 1000;    agent->sa_user_via        = 0;    agent->sa_extra_100       = 0;    agent->sa_pass_100        = 0;    agent->sa_timeout_408     = 1;    agent->sa_pass_408        = 0;    agent->sa_merge_482       = 0;    agent->sa_cancel_2543     = 0;    agent->sa_cancel_487      = 1;    agent->sa_invite_100rel   = 0;    agent->sa_timestamp       = 0;    agent->sa_use_naptr       = 1;    agent->sa_use_srv         = 1;    agent->sa_auto_comp       = 0;    agent->sa_server_rport    = 1;    /* RFC 3261 section 8.1.1.6 */    sip_max_forwards_init(agent->sa_max_forwards)->mf_count = 70;    if (getenv("SIPCOMPACT"))      agent->sa_flags |= MSG_DO_COMPACT;    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 */    outgoing_queue_init(agent->sa_out.inv_proceeding, 0);     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"));

⌨️ 快捷键说明

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