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

📄 nta.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 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 and message utility functions * 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_wait.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/hostdomain.h>#include <sofia-sip/msg_addr.h>#include <sofia-sip/msg_parser.h>#include "nta_internal.h"#include "sofia-sip/nta_stateless.h"#include "sofia-sip/url_tag.h"#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, usize_t 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[], usize_t dlen,					   tport_t const *tport,					   tp_client_t *via);static int complete_response(msg_t *response, 			     int status, char const *phrase, 			     msg_t *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)#ifndef UINT32_MAX#define UINT32_MAX (0xffffffffU)#endifHTABLE_PROTOS_WITH(leg_htable, lht, nta_leg_t, size_t, hash_value_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,			   char const *to_tag);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_WITH(incoming_htable, iht, nta_incoming_t, size_t, hash_value_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);su_inline void incoming_cut_off(nta_incoming_t *irq);su_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 nta_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,				     nta_incoming_t **cancel);static int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip);su_inline int incoming_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip,				tport_t *tport);su_inline int incoming_ack(nta_incoming_t *irq, msg_t *msg, sip_t *sip,			       tport_t *tport);su_inline int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip,				  tport_t *tport);static void request_merge(nta_agent_t *,			  msg_t *msg, sip_t *sip, tport_t *tport,			  char const *to_tag);su_inline int incoming_timestamp(nta_incoming_t *, msg_t *, sip_t *);static void incoming_timer(nta_agent_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 nta_reliable_t *reliable_find(nta_agent_t const *, sip_t const *);static int reliable_recv(nta_reliable_t *rel, 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_WITH(outgoing_htable, oht, nta_outgoing_t, size_t, hash_value_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);su_inline void outgoing_cut_off(nta_outgoing_t *orq);su_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 void outgoing_timer(nta_agent_t *);static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip);/* Internal message passing */union sm_arg_u {  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 char const 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 <sofia-sip/su_debug.h>, #su_log_global, #SOFIA_DEBUG */#ifdef DOXYGENextern char const NTA_DEBUG[]; /* dummy declaration for Doxygen */#endif#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. * * Create 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 @e url is @c NONE (iow, (void*)-1), no server sockets are bound. * @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 when it generates * @Contact and @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,... tagged arguments * * @TAGS * NTATAG_ALIASES(), * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(), * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(), * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(), * NTATAG_EXTRA_100(), NTATAG_GRAYLIST(), * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS() * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(),  * NTATAG_REL100(),  * NTATAG_SERVER_RPORT(), * NTATAG_SIPFLAGS(), * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(), * NTATAG_STATELESS(), * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(), * NTATAG_TIMER_C(), NTATAG_MAX_PROCEEDING(), * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(), * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP(). * * @note The value from following tags are stored, but they currently do nothing: * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME() * * @note It is possible to provide @c (url_string_t*)-1 as @a contact_url.  * In that case, no server sockets are bound. *  * @retval handle to the agent when successful, * @retval NULL upon an error. * * @sa NUTAG_ */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)))) {    unsigned timer_c;    agent->sa_root = root;    agent->sa_callback = callback;    agent->sa_magic = magic;    agent->sa_flags = MSG_DO_CANONIC;    agent->sa_maxsize         = 2 * 1024 * 1024; /* 2 MB */    agent->sa_bad_req_mask    =       /*       * Bit-wise not of these - what is left is suitable for UAs with        * 100rel, timer, events, publish        */      (unsigned) ~(sip_mask_response | sip_mask_proxy | sip_mask_registrar | 		   sip_mask_pref | sip_mask_privacy);    agent->sa_bad_resp_mask   =       (unsigned) ~(sip_mask_request | sip_mask_proxy | sip_mask_registrar | 		   sip_mask_pref | sip_mask_privacy);    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_timer_c         = 185 * 1000;    agent->sa_graylist        = 600;    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);    if (getenv("SIPCOMPACT"))      agent->sa_flags |= MSG_DO_COMPACT;

⌨️ 快捷键说明

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