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

📄 nua_register.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) 2006 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 nua_register.c * @brief REGISTER and registrations * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Martti Mela <Martti.Mela@nokia.com> * @author Kai Vehmanen <Kai.Vehmanen@nokia.com> * * @date Created: Wed Mar  8 11:48:49 EET 2006 ppessi */#include "config.h"/** @internal SU network changed detector argument pointer type */#define SU_NETWORK_CHANGED_MAGIC_T struct nua_s#define TP_CLIENT_T          struct register_usage#include <sofia-sip/string0.h>#include <sofia-sip/su_strlst.h>#include <sofia-sip/su_uniqueid.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/sip_protos.h>#include <sofia-sip/sip_util.h>#include <sofia-sip/sip_status.h>#define NTA_UPDATE_MAGIC_T   struct nua_s#include "nua_stack.h"#include <sofia-sip/hostdomain.h>#include <sofia-sip/nta_tport.h>#include <sofia-sip/tport.h>#include <sofia-sip/tport_tag.h>#define OUTBOUND_OWNER_T struct nua_handle_s#include "outbound.h"#if HAVE_SIGCOMP#include <sigcomp.h>#endif#include <stddef.h>#include <stdlib.h>#include <string.h>#include <limits.h>#include <assert.h>/* ======================================================================== *//* Registrations and contacts */int nua_registration_from_via(nua_registration_t **list,			      nua_handle_t *nh, 			      sip_via_t const *via,			      int public);int nua_registration_add(nua_registration_t **list, nua_registration_t *nr);void nua_registration_remove(nua_registration_t *nr);int nua_registration_set_aor(su_home_t *, nua_registration_t *nr,			     sip_from_t const *aor);int nua_registration_set_contact(nua_handle_t *,				 nua_registration_t *nr,				 sip_contact_t const *m,				 int terminating);void nua_registration_set_ready(nua_registration_t *nr, int ready);/* ====================================================================== *//* REGISTER usage */static char const *nua_register_usage_name(nua_dialog_usage_t const *du);static int nua_register_usage_add(nua_handle_t *nh,				  nua_dialog_state_t *ds,				  nua_dialog_usage_t *du);static void nua_register_usage_remove(nua_handle_t *nh,				      nua_dialog_state_t *ds,				      nua_dialog_usage_t *du,				      nua_client_request_t *cr,				      nua_server_request_t *sr);static void nua_register_usage_update_params(nua_dialog_usage_t const *du,					     nua_handle_preferences_t const *,					     nua_handle_preferences_t const *,					     nua_handle_preferences_t const *);static void nua_register_usage_peer_info(nua_dialog_usage_t *du,					 nua_dialog_state_t const *ds,					 sip_t const *sip);static void nua_register_usage_refresh(nua_handle_t *,				       nua_dialog_state_t *,				       nua_dialog_usage_t *,				       sip_time_t);static int nua_register_usage_shutdown(nua_handle_t *,				       nua_dialog_state_t *,				       nua_dialog_usage_t *);/** @internal @brief REGISTER usage, aka nua_registration_t. */struct register_usage {  nua_registration_t *nr_next, **nr_prev, **nr_list; /* Doubly linked list and its head */  sip_from_t *nr_aor;		/**< AoR for this registration, NULL if none */  sip_contact_t *nr_contact;	/**< Our Contact */  sip_contact_t nr_dcontact[1];	/**< Contact in dialog */  sip_via_t *nr_via;		/**< Corresponding Via headers */  unsigned long nr_min_expires;	/**< Value from 423 negotiation */  /** Status of registration */  unsigned nr_ready:1;  /** Kind of registration.   *   * If nr_default is true, this is not a real registration but placeholder   * for Contact header derived from a transport address.   *   * If nr_secure is true, this registration supports SIPS/TLS.   *   * If nr_public is true, transport should have public address.   */  unsigned nr_default:1, nr_secure:1, nr_public:1, nr_ip4:1, nr_ip6:1;  /** Stack-generated contact */  unsigned nr_by_stack:1;  unsigned:0;    int nr_error_report_id;	/**< ID used to ask for error reports from tport */  sip_route_t *nr_route;	/**< Outgoing Service-Route */  sip_path_t *nr_path;		/**< Incoming Path */  tport_t *nr_tport;		/**< Transport to be used when registered */  nua_dialog_state_t *nr_dialogs; /**< List of our dialogs */#if HAVE_SIGCOMP  struct sigcomp_compartment *nr_compartment;#endif  outbound_t *nr_ob;	/**< Outbound connection */};nua_usage_class const nua_register_usage[1] = {  {    sizeof (struct register_usage),    (sizeof nua_register_usage),    nua_register_usage_add,    nua_register_usage_remove,    nua_register_usage_name,    nua_register_usage_update_params,    nua_register_usage_peer_info,    nua_register_usage_refresh,    nua_register_usage_shutdown  }};static char const *nua_register_usage_name(nua_dialog_usage_t const *du){  return "register";}static int nua_register_usage_add(nua_handle_t *nh,				  nua_dialog_state_t *ds,				  nua_dialog_usage_t *du){  nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du);  if (ds->ds_has_register)    return -1;			/* There can be only one usage */  ds->ds_has_register = 1;  nr->nr_public = 1;		/* */  return 0;}static void nua_register_usage_remove(nua_handle_t *nh,				      nua_dialog_state_t *ds,				      nua_dialog_usage_t *du,				      nua_client_request_t *cr,				      nua_server_request_t *sr){  nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du);  if (nr->nr_list)    nua_registration_remove(nr);	/* Remove from list of registrations */  if (nr->nr_ob)    outbound_unref(nr->nr_ob);#if HAVE_SIGCOMP  if (nr->nr_compartment)    sigcomp_compartment_unref(nr->nr_compartment);  nr->nr_compartment = NULL;#endif  if (nr->nr_error_report_id)    tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0);  if (nr->nr_tport)    tport_unref(nr->nr_tport), nr->nr_tport = NULL;  ds->ds_has_register = 0;	/* There can be only one */}/** @internal Store information about registrar. */static void nua_register_usage_peer_info(nua_dialog_usage_t *du,					 nua_dialog_state_t const *ds,					 sip_t const *sip){  nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du);  if (nr->nr_ob)    outbound_peer_info(nr->nr_ob, sip);}/* ======================================================================== *//* REGISTER */static void nua_register_connection_closed(tp_stack_t *sip_stack,					   nua_registration_t *nr,					   tport_t *tport,					   msg_t *msg,					   int error);/* Interface towards outbound_t */sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,					 su_home_t *home,					 int in_dialog,					 sip_via_t const *v,					 char const *transport,					 char const *m_param,					 ...);static int nua_stack_outbound_refresh(nua_handle_t *,				      outbound_t *ob);static int nua_stack_outbound_status(nua_handle_t *,				     outbound_t *ob,				     int status, char const *phrase,				     tag_type_t tag, tag_value_t value, ...);static int nua_stack_outbound_failed(nua_handle_t *,				     outbound_t *ob,				     int status, char const *phrase,				     tag_type_t tag, tag_value_t value, ...);static int nua_stack_outbound_credentials(nua_handle_t *, auth_client_t **auc);outbound_owner_vtable nua_stack_outbound_callbacks = {    sizeof nua_stack_outbound_callbacks,    /* oo_contact */ nua_handle_contact_by_via,    /* oo_refresh */ nua_stack_outbound_refresh,    /* oo_status */  nua_stack_outbound_status,    /* oo_probe_error */     nua_stack_outbound_failed,    /* oo_keepalive_error */ nua_stack_outbound_failed,    /* oo_credentials */     nua_stack_outbound_credentials  };/**@fn void nua_register(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); *  * Send SIP REGISTER request to the registrar.  * * Request status will be delivered to the application using #nua_r_register * event. When successful the registration will be updated periodically. * * The handle used for registration cannot be used for any other purposes. * * @param nh              Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return *     nothing * * @par Related tags: *     NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), *     NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), NUTAG_M_USERNAME(), *     NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES() * * @par Events: *     #nua_r_register, #nua_i_outbound *  * @par Generating Contact Header * * If the application did not specify the Contact header in the tags, * nua_register() will generate one. It will obtain the schema, IP address * for the host and port number for the Contact URI from the transport * socket. The diplay name is taken from NUTAG_M_DISPLAY(), URL username * part is taken from NUTAG_M_USERNAME(), URI parameters from * NUTAG_M_PARAMS(), and Contact header parameters from NUTAG_M_FEATURES().  * If NUTAG_CALLEE_CAPS(1) is specified, additional Contact header * parameters are generated based on SDP capabilities and SIP @Allow header. *  * Note that @b nua may append a identifier of its own to the @Contact URI * username. Such nua-generated identifier trailer always starts with "=" * (equal sign), rest of the nua-generated identifier may contain any * url-unreserved characters except "=". * * Likewise, nua may add transport parameters (such as "transport=tcp" or * "maddr") to the @Contact URI. It can add addtional header parameters, like * "+sip.instance" or "reg-id", too. * * For instance, if application uses tags like * @code *   nua_register(nh, *                NUTAG_M_DISPLAY("1"), *                NUTAG_M_USERNAME("line-1"), *                NUTAG_M_PARAMS("user=phone"), *                NUTAG_M_FEATURES("audio"), *                NUTAG_CALLEE_CAPS(0), *                TAG_END()) * @endcode * @b nua can generate a Contact header like * @code * Contact: 1 <sip:line-1=SSQAIbjv@192.168.1.200;transport=tcp;user=phone> *   ;audio;reg-id=1 *   ;+sip.instance=urn:uuid:97701ad9-39df-1229-1083-dbc0a85f029c * @endcode * * The incoming request from the proxy should contain the registered contact * URI as the request URI. The application can use the username prefix set * by NUTAG_M_USERNAME() and the non-transport parameters of the request URI * set by NUTAG_M_PARAMS() when determining to which registration the * incoming request belongs. *  * For example, a request line correspoding to the @Contact in above example * may look like: * @code * INVITE sip:line-1=SSQAIbjv@192.168.1.200;user=phone SIP/2.0 * @endcode * * @sa NUTAG_M_DISPLAY(), NUTAG_M_USERNAME(), NUTAG_M_PARAMS(), * NUTAG_M_FEATURES(), NUTAG_CALLEE_CAPS(). * * @par NAT, Firewall and Outbound Support * * Normally, @b nua will start start a protocol engine for outbound * connections used for NAT and firewall traversal and connectivity checks * when registering.  * * @note If the application provides @b nua with a * @Contact header of its own (or includes a SIPTAG_CONTACT(NULL) tag in * nua_register() tags), the outbound protocol engine is not started. It is * assumed that the application knows better what it is doing when it sets * the @Contact, or it is using experimental CPL upload as specified in  * <a href="http://www.ietf.org/internet-drafts/draft-lennox-sip-reg-payload-01.txt"> * draft-lennox-sip-reg-payload-01.txt</a>. * * First, outbound engine will probe for NATs in between UA and registrar.  * It will send a REGISTER request as usual. Upon receiving the response it * checks for the presence of "received" and "rport" parameters in the Via * header returned by registrar. The presence of NAT is determined from the * "received" parameter in a Via header. When a REGISTER request was sent, * the stack inserted the actual source IP address in the Via header: if * that is different from the source IP address seen by the registrar, the * registrar inserts the source IP address it sees into the "received" * parameter. * * Please note that an ALG (application-level gateway) modifying the Via * headers in outbound requests and again in incoming responses will make * the above-described NAT check to fail. * * The response to the initial REGISTER should also include option tags * indicating whether registrar supports various SIP extension options: @e * outbound, @e pref, @e path, @e gruu. * * Basically, @e outbound means that instead of registering its contact URI * with a particular address-of-record URI, the user-agent registers a * transport-level connection. Such a connection is identified on the * Contact header field with an instance identifier, application-provided * @ref NUTAG_INSTANCE() "unique string" identifying the user-agent instance * and a stack-generated numeric index identifying the transport-level * connection. * * If the @e outbound extension is supported, NUTAG_OUTBOUND() contains * option string "outbound" and the application has provided an instance * identifer to the stack with NUTAG_INSTANCE(), the nua_register() will try * to use outbound. * * If @e outbound is not supported, nua_register() has to generate a URI * that can be used to reach it from outside. It will check for public * transport addresses detected by underlying stack with, e.g., STUN, UPnP * or SOCKS. If there are public addresses, nua_register() will use them. If * there is no public address, it will try to generate a Contact URI from * the "received" and "rport" parameters found in the Via header of the * response message. * * @todo Actually generate public addresses. * * You can disable this kind of NAT traversal by setting "no-natify" into * NUTAG_OUTBOUND() options string. *  * @par GRUU and Service-Route * * After a successful response to the REGISTER request has been received, * nua_register() will update the information about the registration based * on it. If there is a "gruu" parameter included in the response, * nua_register() will save it and use the gruu URI in the Contact header

⌨️ 快捷键说明

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