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

📄 outbound.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 outbound.c * @brief Implementation of SIP NAT traversal and outbound * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Kai Vehmanen <Kai.Vehmanen@nokia.com> * @author Martti Mela <Martti Mela@nokia.com> * * @date Created: Wed May 10 12:11:54 EEST 2006 ppessi */#include "config.h"#define NTA_OUTGOING_MAGIC_T struct outbound#include <outbound.h>#include <sofia-sip/hostdomain.h>#include <sofia-sip/sip.h>#include <sofia-sip/sip_protos.h>#include <sofia-sip/sip_util.h>#include <sofia-sip/sip_status.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/tport.h>#include <sofia-sip/nta_tport.h>#include <sofia-sip/su_md5.h>#include <sofia-sip/su_uniqueid.h>#include <sofia-sip/token64.h>#define SU_LOG (nua_log)#include <sofia-sip/su_debug.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <assert.h>struct outbound {  su_home_t ob_home[1];  outbound_owner_vtable  const *ob_oo;			/**< Callbacks */  outbound_owner_t *ob_owner;	/**< Backpointer */  su_root_t *ob_root;		/**< Root for timers and stuff */  nta_agent_t *ob_nta;		/**< SIP transactions */  char ob_cookie[32];		/**< Our magic cookie */  struct outbound_prefs {    unsigned interval;	/**< Default keepalive interval for datagram */    unsigned stream_interval;	/**< Default keepalive interval for streams */    unsigned gruuize:1;		/**< Establish a GRUU */    unsigned outbound:1;	/**< Try to use outbound */    unsigned natify:1;		/**< Try to detect NAT */    unsigned okeepalive:1;	/**< Connection keepalive with OPTIONS */    unsigned validate:1;	/**< Validate registration with OPTIONS */    /* How to detect NAT binding or connect to outbound: */    unsigned use_connect:1;	/**< Use HTTP connect */    unsigned use_rport:1;	/**< Use received/rport */    unsigned use_socks:1;	/**< Detect and use SOCKS V5 */    unsigned use_upnp:1;	/**< Detect and use UPnP */    unsigned use_stun:1;	/**< Detect and try to use STUN */    unsigned :0;  } ob_prefs;  struct outbound_info {    /* See enum outbound_feature: */    /* 0 do not support, 1 - perhaps supports, 2 - supports, 3 - requires */    unsigned gruu:2, outbound:2, pref:2;  } ob_info;  /** Source of Contact header */  unsigned ob_by_stack:1;  /** Self-generated contacts */  unsigned ob_contacts:1, :0;  /* The registration state machine. */  /** Initial REGISTER containing ob_rcontact has been sent */  unsigned ob_registering:1;  /** 2XX response to REGISTER containg ob_rcontact has been received */  unsigned ob_registered:1;  /**The registration has been validated:   * We have successfully sent OPTIONS to ourselves.   */  unsigned ob_validated:1;  /** The registration has been validated once.   *   We have successfully sent OPTIONS to ourselves, so do not give   *   up if OPTIONS probe fails.   */  unsigned ob_once_validated:1;  unsigned :0;  char const *ob_instance;	/**< Our instance ID */  int32_t ob_reg_id;		/**< Flow-id */  char const *ob_features;	/**< Feature parameters for rcontact */  sip_contact_t *ob_rcontact;	/**< Our contact */  sip_contact_t *ob_dcontact;	/**< Contact for dialogs */  sip_contact_t *ob_previous;	/**< Stale contact */  sip_contact_t *ob_gruu;	/**< Contact added to requests */  sip_via_t *ob_via;		/**< Via header used to generate contacts */  sip_contact_t *ob_obp;	/**< Contacts from outbound proxy */  char *ob_nat_detected;	/**< Our public address */  char *ob_nat_port;		/**< Our public port number */  void *ob_stun;		/**< Stun context */  void *ob_upnp;		/**< UPnP context  */  struct {    char *sipstun;		/**< Stun server usable for keep-alives */    unsigned interval;		/**< Interval. */    su_timer_t *timer;		/**< Keep-alive timer */    msg_t *msg;			/**< Keep-alive OPTIONS message */    nta_outgoing_t *orq;	/**< Keep-alive OPTIONS transaction */    auth_client_t *auc[1];	/**< Authenticator for OPTIONS */    /** Progress of registration validation */    unsigned validating:1, validated:1,:0;  } ob_keepalive;		/**< Keepalive informatio */};staticint outbound_nat_detect(outbound_t *ob,       			 sip_t const *request,       			 sip_t const *response);/** Return values for outbound_nat_detect(). */enum {  ob_nat_error = -1,		/* or anything below zero */  ob_no_nat = 0,  ob_nat_detected = 1,  ob_nat_changed = 2};/* ---------------------------------------------------------------------- */#define SIP_METHOD_UNKNOWN sip_method_unknown, NULL/** Content-Type sent in OPTIONS probing connectivity */char const * const outbound_content_type = "application/vnd.nokia-register-usage";staticint outbound_check_for_nat(outbound_t *ob,			   sip_t const *request,			   sip_t const *response);enum outbound_feature {  outbound_feature_unsupported = 0,  outbound_feature_unsure = 1,  outbound_feature_supported = 2,  outbound_feature_required = 3};static enum outbound_feature feature_level(sip_t const *sip,					   char const *tag, int level);static int outbound_contacts_from_via(outbound_t *ob,				      sip_via_t const *via);/* ---------------------------------------------------------------------- */outbound_t *outbound_new(outbound_owner_t *owner,	     outbound_owner_vtable const *owner_methods,	     su_root_t *root,	     nta_agent_t *agent,	     char const *instance){  outbound_t *ob;  if (!owner || !owner_methods || !root || !agent)    return NULL;  ob = su_home_clone((su_home_t *)owner, sizeof *ob);    if (ob) {    su_md5_t md5[1];    uint8_t digest[SU_MD5_DIGEST_SIZE];    su_guid_t guid[1];    ob->ob_owner = owner;    ob->ob_oo = owner_methods;    ob->ob_root = root;    ob->ob_nta = agent;    if (instance)      ob->ob_instance = su_strcat_all(ob->ob_home, "+sip.instance=\"<", instance, ">\"", NULL);    ob->ob_reg_id = 0;    /* Generate a cookie (used as Call-ID) for us */    su_md5_init(md5);    su_guid_generate(guid);    if (instance)      su_md5_update(md5, (void *)instance, strlen(instance));    su_md5_update(md5, (void *)guid, sizeof guid);    su_md5_digest(md5, digest);    token64_e(ob->ob_cookie, sizeof ob->ob_cookie, digest, sizeof digest);        if (instance && !ob->ob_instance)      su_home_unref(ob->ob_home), ob = NULL;  }  return ob;}void outbound_unref(outbound_t *ob){  if (ob->ob_keepalive.timer)    su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL;  if (ob->ob_keepalive.orq)    nta_outgoing_destroy(ob->ob_keepalive.orq), ob->ob_keepalive.orq = NULL;  if (ob->ob_keepalive.msg)    msg_destroy(ob->ob_keepalive.msg), ob->ob_keepalive.msg = NULL;  su_home_unref(ob->ob_home);}#include <sofia-sip/bnf.h>/** Set various outbound and nat-traversal related options. */int outbound_set_options(outbound_t *ob,			 char const *options,			 unsigned interval,			 unsigned stream_interval){  struct outbound_prefs prefs[1] = {{ 0 }};  char const *s;  prefs->interval = interval;  prefs->stream_interval = stream_interval;  prefs->gruuize = 1;  prefs->outbound = 0;  prefs->natify = 1;  prefs->okeepalive = 1;  prefs->validate = 1;  prefs->use_rport = 1;#define MATCH(v) (len == sizeof(#v) - 1 && strncasecmp(#v, s, len) == 0)  for (s = options; s && s[0]; ) {    int len = span_token(s);    int value = 1;    if (len > 3 && strncasecmp(s, "no-", 3) == 0)      value = 0, s += 3, len -= 3;    else if (len > 4 && strncasecmp(s, "not-", 4) == 0)      value = 0, s += 4, len -= 4;    else if (len > 3 && strncasecmp(s, "no_", 3) == 0)      value = 0, s += 3, len -= 3;    else if (len > 4 && strncasecmp(s, "not_", 4) == 0)      value = 0, s += 4, len -= 4;    if (len == 0)      break;    else if (MATCH(gruuize)) prefs->gruuize = value;    else if (MATCH(outbound)) prefs->outbound = value;    else if (MATCH(natify)) prefs->natify = value;    else if (MATCH(validate)) prefs->validate = value;    else if (MATCH(options-keepalive)) prefs->okeepalive = value;    else if (MATCH(options_keepalive)) prefs->okeepalive = value;    else if (MATCH(use-connect)) prefs->use_connect = value;    else if (MATCH(use_connect)) prefs->use_connect = value;    else if (MATCH(use-rport) || MATCH(use_rport)) prefs->use_rport = value;    else if (MATCH(use-socks) || MATCH(use_socks)) prefs->use_socks = value;    else if (MATCH(use-upnp) || MATCH(use_upnp)) prefs->use_upnp = value;    else if (MATCH(use-stun) || MATCH(use_stun)) prefs->use_stun = value;    else      SU_DEBUG_1(("outbound_t: unknown option \"%.*s\"\n", len, s));    s += len;    len = strspn(s, " \t\n\r,;");    if (len == 0)      break;    s += len;  }  if (s && s[0]) {    SU_DEBUG_1(("outbound_t: invalid options \"%s\"\n", options));    return -1;  }  if (prefs->natify &&      !(prefs->outbound ||	prefs->use_connect ||	prefs->use_rport ||	prefs->use_socks ||	prefs->use_upnp ||	prefs->use_stun)) {    SU_DEBUG_1(("outbound(%p): no nat traversal method given\n", ob->ob_owner));  }  ob->ob_prefs = *prefs;  ob->ob_reg_id = prefs->outbound ? 1 : 0;  return 0;}/** Set the feature string (added to the Contact header when registering). */int outbound_set_features(outbound_t *ob, char *features){  char *old_features = (char *)ob->ob_features;  char *new_features = su_strdup(ob->ob_home, features);  if (features && !new_features)    return -1;  ob->ob_features = new_features;  su_free(ob->ob_home, old_features);  return 0;}/* ---------------------------------------------------------------------- *//** Hook for sending register request with extra outbound-ish headers. */nta_outgoing_t *outbound_register_request(outbound_t *ob, int terminating, 					  sip_contact_t *stack_contact,					  nta_agent_t *nta,					  nta_response_f *callback,					  nta_outgoing_magic_t *magic,					  url_string_t *next_hop,					  msg_t *msg,					  tag_type_t tag, tag_value_t value,					  ...){  sip_contact_t *previous_contact = NULL;  ta_list ta;  nta_outgoing_t *orq;  if (stack_contact) {    if (ob) {      if (ob->ob_contacts)	stack_contact = ob->ob_rcontact;      previous_contact = ob->ob_previous;    }  }  ta_start(ta, tag, value);  orq = nta_outgoing_mcreate(nta, callback, magic, next_hop, msg,			     TAG_IF(previous_contact,				    SIPTAG_CONTACT(previous_contact)),			     TAG_IF(stack_contact,				    SIPTAG_CONTACT(stack_contact)),			     ta_tags(ta));  ta_end(ta);  if (orq && ob)    ob->ob_registering = 1;  return orq;}/** Process response to REGISTER request */int outbound_register_response(outbound_t *ob,			       int terminating,			       sip_t const *request,			       sip_t const *response){  int status, reregister;  if (!ob)    return 0;  assert(!request || request->sip_request);  assert(!response || response->sip_status);    if (!response || !request)    return 0;  if (terminating) {    ob->ob_registered = ob->ob_registering = 0;    return 0;			/* Cleanup is done separately */  }    reregister = outbound_check_for_nat(ob, request, response);  if (reregister)    return reregister;

⌨️ 快捷键说明

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