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

📄 nua_register.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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> * * @date Created: Wed Mar  8 11:48:49 EET 2006 ppessi */#include "config.h"#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_LEG_MAGIC_T      struct nua_handle_s#define NTA_OUTGOING_MAGIC_T struct nua_handle_s#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>#if !defined(random) && defined(_WIN32)#define random rand#endif/* ======================================================================== *//* Registrations and contacts */int nua_registration_from_via(nua_registration_t **list,			      su_home_t *home,			      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(su_home_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);static void nua_register_usage_peer_info(nua_dialog_usage_t *du,					 nua_dialog_state_t const *ds,					 sip_t const *sip);/** 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 */  /** 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;  /** Stack-generated contact */  unsigned nr_by_stack:1, :0;  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_peer_info,  }};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_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  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 restart_register(nua_handle_t *nh, tagi_t *tags);static void refresh_register(nua_handle_t *, nua_dialog_usage_t *, sip_time_t);static int process_response_to_register(nua_handle_t *nh,					nta_outgoing_t *orq,					sip_t const *sip);static void unregister_expires_contacts(msg_t *msg, sip_t *sip);/* Interface towards outbound_t */static int nua_stack_outbound_features(nua_handle_t *nh, outbound_t *ob);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,    nua_stack_outbound_refresh,    nua_stack_outbound_status,    nua_stack_outbound_failed,    nua_stack_outbound_failed,    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(), * * @par Events: *     #nua_r_register, #nua_i_outbound * * @par NAT, Firewall and Outbound Support * * If the application did not include the Contact header in the tags, * nua_register() will generate one and start a protocol engine for outbound * connections used for NAT and firewall traversal and connectivity checks.  * * First, nua_register() 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 valid "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 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 feature tags * indicating whether registrar supports various SIP extensions: @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 * fields of dialog-establishing messages, such as INVITE or SUBSCRIBE.  * Also, if the registrar has included a Service-Route header in the * response, and the service route feature has not been disabled using * NUTAG_SERVICE_ROUTE_ENABLE(), the route URIs from the Service-Route * header will be used for initial non-REGISTER requests. * * The #nua_r_register message will include the contact header and route * used in with the registration. * * @par Registration Keep-Alive * * After the registration has successfully completed the nua_register() will * validate the registration and initiate the keepalive mechanism, too. The * user-agent validates the registration by sending a OPTIONS requests to * itself. If there is an error, nua_register() will indicate that to the * application using nua_i_outbound event, and start unregistration * procedure (unless that has been explicitly disabled). * * You can disable validation by inserting "no-validate" into * NUTAG_OUTBOUND() string. * * The keepalive mechanism depends on the network features detected earlier.  * If @a outbound extension is used, the STUN keepalives will be used.  * Otherwise, NUA stack will repeatedly send OPTIONS requests to itself. In * order to save bandwidth, it will include Max-Forwards: 0 in the * keep-alive requests, however. The keepalive interval is determined by * NUTAG_KEEPALIVE() parameter. If the interval is 0, no keepalive messages * is sent. * * You can disable keepalive OPTIONS by inserting "no-options-keepalive" * into NUTAG_OUTBOUND() string. Currently there are no other keepalive * mechanisms available. * * The value of NUTAG_KEEPALIVE_STREAM(), if specified, is used to indicate * the desired transport-layer keepalive interval for stream-based * transports like TLS and TCP. * * @sa NUTAG_OUTBOUND() and tags. *//** @var nua_event_e::nua_r_register * * Answer to outgoing REGISTER. * * The REGISTER may be sent explicitly by nua_register() or implicitly by * NUA state machines. The @a status may be 100 even if the real response * status returned is different if the REGISTER request has been restarted. * * @param nh     operation handle associated with the call * @param hmagic operation magic associated with the call * @param status registration status * @param sip    response to REGISTER request or NULL upon an error *               (error code and message are in status an phrase parameters) * @param tags   empty *//** @var nua_event_e::nua_i_outbound * * Answer to outgoing REGISTER. * * The REGISTER may be sent explicitly by nua_register() or * implicitly by NUA state machine. * * @param nh     operation handle associated with the call * @param hmagic operation magic associated with the call * @param sip    response to REGISTER request or NULL upon an error *               (error code and message are in status an phrase parameters) * @param tags   empty *//**@fn void nua_unregister(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * Unregister.  * * Send a REGISTER request with expiration time 0. This removes the  * registration from the registrar. If the handle was earlier used  * with nua_register() the periodic updates will be terminated.  * * If a SIPTAG_CONTACT_STR() with argument "*" is used, all the * registrations will be removed from the registrar otherwise only the * contact address belonging to the NUA stack is removed. * * @param nh              Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return *     nothing * * @par Related tags: *     NUTAG_REGISTRAR() \n *     Tags in <sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR() * * @par Events: *     #nua_r_unregister *//** @var nua_event_e::nua_r_unregister * * Answer to outgoing un-REGISTER. * * @param nh     operation handle associated with the call * @param hmagic operation magic associated with the call * @param sip    response to REGISTER request or NULL upon an error *               (error code and message are in status and phrase parameters) * @param tags   empty */intnua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e,		   tagi_t const *tags){  nua_dialog_usage_t *du;  nua_registration_t *nr = NULL;  outbound_t *ob = NULL;  struct nua_client_request *cr = nh->nh_cr;  msg_t *msg = NULL;  sip_t *sip;  int terminating = e != nua_r_register;  if (nh->nh_special && nh->nh_special != nua_r_register)    return UA_EVENT2(e, 900, "Invalid handle for REGISTER");  if (cr->cr_orq)    return UA_EVENT2(e, 900, "Request already in progress");  nua_stack_init_handle(nua, nh, nh_has_register, "", TAG_NEXT(tags));  nh->nh_special = nua_r_register;  du = nua_dialog_usage_add(nh, nh->nh_ds, nua_register_usage, NULL);  if (!du)    return UA_EVENT1(e, NUA_INTERNAL_ERROR);  nr = nua_dialog_usage_private(du); assert(nr);  nua_registration_add(&nh->nh_nua->nua_registrations, nr);  if (!terminating && du->du_terminating)    return UA_EVENT2(e, 900, "Unregister in progress");  if (cr->cr_msg)    msg_destroy(cr->cr_msg), cr->cr_msg = NULL;  /* Use original message as template when unregistering */  if (terminating)		    cr->cr_msg = msg_ref_create(du->du_msg);  msg = nua_creq_msg(nua, nh, cr, cr->cr_msg != NULL,		     SIP_METHOD_REGISTER,		     TAG_IF(!terminating, NUTAG_USE_DIALOG(1)),		     TAG_NEXT(tags));  sip = sip_object(msg);  if (!msg || !sip)    goto error;  if (!nr->nr_aor) {    if (nua_registration_set_aor(nh->nh_home, nr, sip->sip_to) < 0)      goto error;  }  du->du_terminating = terminating;  if (du->du_msg == NULL)    du->du_msg = msg_ref_create(cr->cr_msg); /* Save original message */  if (terminating)    /* Add Expires: 0 and remove the expire parameters from contacts */    unregister_expires_contacts(msg, sip);  if (nua_registration_set_contact(nh->nh_home, nr, sip->sip_contact, terminating) < 0)    goto error;    ob = nr->nr_ob;    if (!ob && (NH_PGET(nh, outbound) || NH_PGET(nh, instance))) {    nr->nr_ob = ob = outbound_new(nh, &nua_stack_outbound_callbacks,				  nh->nh_nua->nua_root,				  nh->nh_nua->nua_nta,

⌨️ 快捷键说明

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