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

📄 nua_stack.c

📁 Internet Phone, Chat, Conferencing
💻 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 nua_stack.c * @brief Nokia User Agent (NUA) implementation * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Kai Vehmanen <Kai.Vehmanen@nokia.com> * @author Martti Mela <Martti Mela@nokia.com> * @author Remeres Jacobs <Remeres.Jacobs@nokia.com> * @author Tat Chan <Tat.Chan@nokia.com> * * @date Created: Wed Feb 14 18:32:58 2001 ppessi */#include "config.h"#include <sofia-sip/su_tag_class.h>#include <sofia-sip/su_tag_class.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su_strlst.h>#include <sofia-sip/su_uniqueid.h>#include <sofia-sip/su_tag_io.h>#define SU_ROOT_MAGIC_T   struct nua_s#define SU_MSG_ARG_T      struct event_s#define NUA_SAVED_EVENT_T su_msg_t *#define NTA_AGENT_MAGIC_T    struct nua_s#define NTA_LEG_MAGIC_T      struct nua_handle_s#define NTA_OUTGOING_MAGIC_T struct nua_handle_s#define NTA_INCOMING_MAGIC_T struct nua_handle_s#include <sofia-sip/sip.h>#include <sofia-sip/sip_header.h>#include <sofia-sip/sip_status.h>#include <sofia-sip/sip_util.h>#include <sofia-sip/tport_tag.h>#include <sofia-sip/nta.h>#include <sofia-sip/nta_tport.h>#include <sofia-sip/auth_client.h>#include <sofia-sip/soa.h>#include "sofia-sip/nua.h"#include "sofia-sip/nua_tag.h"#include "nua_stack.h"#include <stddef.h>#include <stdlib.h>#include <string.h>#include <limits.h>#include <stdio.h>#include <assert.h>/* ======================================================================== * *                       Protocol stack side * * ======================================================================== */nua_handle_t *nh_create(nua_t *nua, tag_type_t t, tag_value_t v, ...);static void nh_append(nua_t *nua, nua_handle_t *nh);static void nh_remove(nua_t *nua, nua_handle_t *nh);static int nh_authorize(nua_handle_t *nh,			tag_type_t tag, tag_value_t value, ...);static int nh_challenge(nua_handle_t *nh, sip_t const *sip);static void nua_stack_timer(nua_t *nua, su_timer_t *t, su_timer_arg_t *a);static void ua_set_from(nua_t *nua, sip_from_t const *f, char const *fromstr);static void ua_init_instance(nua_t *nua);static void ua_init_contact(nua_t *nua);/* ---------------------------------------------------------------------- *//* Constant data *//** Methods allowed by default. */static char const nua_allow_str[] ="INVITE, ACK, BYE, CANCEL, OPTIONS, PRACK, ""MESSAGE, SUBSCRIBE, NOTIFY, REFER, UPDATE";/** Default internal error */char const nua_500_error[] = "Internal NUA Error";char const nua_application_sdp[] = "application/sdp";#define NUA_STACK_TIMER_INTERVAL (1000)/* ---------------------------------------------------------------------- * Initialization & deinitialization */int nua_stack_init(su_root_t *root, nua_t *nua){  su_home_t *home;  void *sip_parser = NULL;  url_string_t const *contact = NULL;  url_string_t const *sips_contact = NULL;  sip_from_t const *from = NULL;  char const *from_str = NULL;  char const *certificate_dir = NULL;  char const *uicc_name = "default";  nua_handle_t *dnh;  nua_handle_preferences_t *dnhp;  int media_enable = 1;  soa_session_t *soa = NULL;  char const *soa_name = NULL;  static int initialized_logs = 0;  enter;  if (!initialized_logs) {    extern su_log_t tport_log[];    extern su_log_t nta_log[];    extern su_log_t nea_log[];    extern su_log_t iptsec_log[];    su_log_init(tport_log);    su_log_init(nta_log);    su_log_init(nea_log);    su_log_init(iptsec_log);    initialized_logs = 1;  }  home = nua->nua_home;  dnh = su_home_clone(home, sizeof (*dnh) + sizeof(*dnhp));  if (!dnh)    return -1;  nua_handle_ref(dnh);  nua->nua_root = root;  nua->nua_handles_tail = &nua->nua_handles;  nh_append(nua, dnh);  dnh->nh_valid = nua_handle;  dnh->nh_nua = nua;  dnh->nh_ds->ds_local = sip_from_init(nua->nua_from);  dnh->nh_ds->ds_remote = nua->nua_from;  dnh->nh_ref_by_stack = 1; dnh->nh_ref_by_user = 1;  dnh->nh_prefs = dnhp = (void *)(dnh + 1);  /* Set some defaults */  DNHP_SET(dnhp, retry_count, 3);  DNHP_SET(dnhp, max_subscriptions, 20);  DNHP_SET(dnhp, invite_enable, 1);  DNHP_SET(dnhp, auto_alert, 0);  DNHP_SET(dnhp, early_media, 0);  DNHP_SET(dnhp, auto_answer, 0);  DNHP_SET(dnhp, auto_ack, 1);  DNHP_SET(dnhp, invite_timeout, 120);  DNHP_SET(dnhp, natify, 1);  DNHP_SET(dnhp, gruuize, 1);  DNHP_SET(dnhp, session_timer, 1800);  DNHP_SET(dnhp, min_se, 120);  DNHP_SET(dnhp, refresher, nua_no_refresher);  DNHP_SET(dnhp, update_refresh, 0);  DNHP_SET(dnhp, message_enable, 1);  DNHP_SET(dnhp, win_messenger_enable, 0);  if (getenv("PIMIW_HACK") != 0)    DNHP_SET(dnhp, message_auto_respond, 1);  DNHP_SET(dnhp, media_features,  0);  DNHP_SET(dnhp, callee_caps, 0);  DNHP_SET(dnhp, service_route_enable, 1);  DNHP_SET(dnhp, path_enable, 1);  DNHP_SET(dnhp, refer_expires, 300);  DNHP_SET(dnhp, substate, nua_substate_active);  DNHP_SET(dnhp, allow, sip_allow_make(dnh->nh_home, nua_allow_str));  DNHP_SET(dnhp, supported, sip_supported_make(dnh->nh_home, "timer, 100rel"));  DNHP_SET(dnhp, user_agent,	   sip_user_agent_make(dnh->nh_home, PACKAGE_NAME "/" PACKAGE_VERSION));  /* Set initial nta parameters */  tl_gets(nua->nua_args,	  NUTAG_URL_REF(contact),	  SIPTAG_FROM_REF(from),	  SIPTAG_FROM_STR_REF(from_str),	  NUTAG_SIPS_URL_REF(sips_contact),	  NUTAG_CERTIFICATE_DIR_REF(certificate_dir),	  NUTAG_SIP_PARSER_REF(sip_parser),	  NUTAG_UICC_REF(uicc_name),	  NUTAG_MEDIA_ENABLE_REF(media_enable),	  /* NUTAG_SOA_SESSION_REF(soa), */	  NUTAG_SOA_NAME_REF(soa_name),	  TAG_NULL());#if HAVE_UICC_H  if (uicc_name)    nua->nua_uicc = uicc_create(root, uicc_name);#endif  nua->nua_nta = nta_agent_create(root, NONE, NULL, NULL,				  TPTAG_CERTIFICATE(certificate_dir),				  NTATAG_TAG_3261(0),				  TAG_NEXT(nua->nua_args));  if (!nua->nua_nta)    return -1;  if (!contact && !sips_contact) {    if (nta_agent_add_tport(nua->nua_nta, NULL,			    TAG_NEXT(nua->nua_args)) < 0 &&	nta_agent_add_tport(nua->nua_nta, URL_STRING_MAKE("sip:*:*"),			    TAG_NEXT(nua->nua_args)) < 0)      return -1;  }  else if ((!contact ||       nta_agent_add_tport(nua->nua_nta, contact,			   TAG_NEXT(nua->nua_args)) < 0) &&      (!sips_contact ||       nta_agent_add_tport(nua->nua_nta, sips_contact,			   TAG_NEXT(nua->nua_args)) < 0)) {    return -1;  }  nua->nua_media_enable = media_enable;  nta_agent_set_params(nua->nua_nta,		       NTATAG_UA(1),		       NTATAG_MERGE_482(1),		       NTATAG_RPORT(1),	/* XXX */#if HAVE_SOFIA_SMIME		       NTATAG_SMIME(nua->sm),#endif		       TAG_NEXT(nua->nua_args));  nua->nua_invite_accept = sip_accept_make(home, SDP_MIME_TYPE);  if (media_enable) {    if (soa == NULL)      soa = soa_create(soa_name, nua->nua_root, nua->nua_dhandle);    dnh->nh_soa = soa;    soa_set_params(soa, TAG_NEXT(nua->nua_args));  }  dnh->nh_ds->ds_leg = nta_leg_tcreate(nua->nua_nta,				       nua_stack_process_request, dnh,				       NTATAG_NO_DIALOG(1),				       TAG_END());  ua_init_instance(nua);  ua_init_contact(nua);  ua_set_from(nua, from, from_str);  nua->nua_timer = su_timer_create(su_root_task(root),				   NUA_STACK_TIMER_INTERVAL);  if (!(dnh->nh_ds->ds_leg &&	dnhp->nhp_allow &&	dnhp->nhp_supported &&	(nua->nua_contact || nua->nua_sips_contact) &&	nua->nua_from &&	nua->nua_timer))    return -1;  nua_stack_timer(nua, nua->nua_timer, NULL);  nua->nua_args = NULL;  return 0;}void nua_stack_deinit(su_root_t *root, nua_t *nua){  enter;  su_timer_destroy(nua->nua_timer), nua->nua_timer = NULL;  nta_agent_destroy(nua->nua_nta), nua->nua_nta = NULL;}/** Set the default from field */void ua_set_from(nua_t *nua, sip_from_t const *f, char const *str){  sip_from_t from[1], *f0;#if HAVE_UICC_H  /* XXX: add */#endif  sip_from_init(from);  if (f) {    from->a_display = f->a_display;    *from->a_url = *f->a_url;    f0 = sip_from_dup(nua->nua_home, from);  }  else if (str) {    f0 = sip_from_make(nua->nua_home, str);    if (f0)      *from = *f0, f0 = from, f0->a_params = NULL;  }  else {    sip_contact_t *m;    m = nua->nua_contact ? nua->nua_contact : nua->nua_sips_contact;    from->a_display = m->m_display;    *from->a_url = *m->m_url;    f0 = sip_from_dup(nua->nua_home, from);  }  if (f0)    *nua->nua_from = *f0;}/** Initialize instance ID. */staticvoid ua_init_instance(nua_t *nua){  nua_handle_t *dnh = nua->nua_dhandle;  nua_handle_preferences_t *dnhp = dnh->nh_prefs;  char str[su_guid_strlen + 1];  su_guid_t guid[1];  su_guid_generate(guid);  /*   * Guid looks like "NNNNNNNN-NNNN-NNNN-NNNN-XXXXXXXXXXXX"   * where NNNNNNNN-NNNN-NNNN-NNNN is timestamp and XX is MAC address   * (but we use usually random ID for MAC because we do not have   *  guid generator available for all processes within node)   */  su_guid_sprintf(str, su_guid_strlen + 1, guid);  DNHP_SET(dnhp, instance, su_sprintf(dnh->nh_home, "urn:uuid:%s", str));}staticvoid ua_init_a_contact(nua_t *nua, su_home_t *home, sip_contact_t *m);/** Initialize our contacts. */void ua_init_contact(nua_t *nua){  su_home_t home[1] = { SU_HOME_INIT(home) };  sip_via_t *v;  int sip = 0, sips = 0;  sip_contact_t *m;  for (v = nta_agent_via(nua->nua_nta); v; v = v->v_next) {    if (strcasecmp(v->v_protocol, sip_transport_tls) != 0) {      if (!sip) {	m = sip_contact_create_from_via(home, v, NULL);	if (m) {	  ua_init_a_contact(nua, home, m);	  sip = 1;	}      }    }    else if (!sips) {      m = sip_contact_create_from_via(home, v, NULL);      if (m) {	ua_init_a_contact(nua, home, m);	sips = 1;      }    }    if (sip && sips)      break;  }  su_home_deinit(home);}staticvoid ua_init_a_contact(nua_t *nua, su_home_t *home, sip_contact_t *m){  su_strlst_t *l = su_strlst_create(home);  nua_handle_t *dnh = nua->nua_dhandle;  int i;  if (DNH_PGET(dnh, instance)) {    char const *instance = DNH_PGET(dnh, instance);    instance = su_sprintf(home, "+sip.instance=\"<%s>\"", instance);    msg_header_replace_param(home, m->m_common, instance);  }  if (DNH_PGET(dnh, callee_caps)) {    sip_allow_t const *allow = DNH_PGET(dnh, allow);    if (allow) {      char *methods;      if (allow->k_items)	for (i = 0; allow->k_items[i]; i++)	  su_strlst_append(l, allow->k_items[i]);      methods = su_strlst_join(l, home, ",");      methods = su_sprintf(home, "methods=\"%s\"", methods);      msg_header_replace_param(home, m->m_common, methods);    }    if (dnh->nh_soa) {      char **media = soa_media_features(dnh->nh_soa, 0, home);      while (*media) {	msg_header_replace_param(home, m->m_common, *media);	media++;      }    }  }  m = sip_contact_dup(nua->nua_home, m);  if (m) {    if (m->m_url->url_type == url_sip)      su_free(nua->nua_home, nua->nua_contact),	nua->nua_contact = m;    else      su_free(nua->nua_home, nua->nua_sips_contact),	nua->nua_sips_contact = m;  }}/* ---------------------------------------------------------------------- * Sending events to client application */static void nua_stack_shutdown(nua_t *);void  nua_stack_authenticate(nua_t *, nua_handle_t *, nua_event_t, tagi_t const *),  nua_stack_respond(nua_t *, nua_handle_t *, int , char const *, tagi_t const *),  nua_stack_destroy_handle(nua_t *, nua_handle_t *, tagi_t const *);/* Notifier */void  nua_stack_authorize(nua_t *, nua_handle_t *, nua_event_t, tagi_t const *),

⌨️ 快捷键说明

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