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

📄 test_proxy.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 test_proxy.c * @brief Extremely simple proxy and registrar for testing nua * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Thu Nov  3 22:49:46 EET 2005 */#include "config.h"#include <string.h>struct proxy;struct proxy_transaction;struct registration_entry;struct binding;#define SU_ROOT_MAGIC_T struct proxy#define NTA_LEG_MAGIC_T struct proxy#define NTA_OUTGOING_MAGIC_T struct proxy_transaction#define NTA_INCOMING_MAGIC_T struct proxy_transaction#include <sofia-sip/su_wait.h>#include <sofia-sip/nta.h>#include <sofia-sip/sip_header.h>#include <sofia-sip/sip_status.h>#include <sofia-sip/sip_util.h>#include <sofia-sip/auth_module.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/msg_addr.h>#include <stdlib.h>#include <assert.h>#define LIST_PROTOS(STORAGE, PREFIX, T)			 \STORAGE void PREFIX ##_insert(T **list, T *node),	 \        PREFIX ##_remove(T *node)			 #define LIST_BODIES(STORAGE, PREFIX, T, NEXT, PREV)	  \STORAGE void PREFIX ##_insert(T **list, T *node)   \{							 \  if ((node->NEXT = *list)) {				 \    node->PREV = node->NEXT->PREV;			 \    node->NEXT->PREV = &node->NEXT;			 \  }							 \  else							 \    node->PREV = list;					 \  *list = node;						 \}							 \STORAGE void PREFIX ##_remove(T *node)			 \{							 \  if (node->PREV)					 \    if ((*node->PREV = node->NEXT))			 \      node->NEXT->PREV = node->PREV;			 \  node->PREV = NULL;					 \}							 \extern int LIST_DUMMY_VARIABLE#include <test_proxy.h>struct proxy {  su_home_t    home[1];  su_root_t   *parent;  su_clone_r   clone;  tagi_t      *tags;  su_root_t   *root;  auth_mod_t  *auth;   nta_agent_t *agent;  url_t const *uri;    nta_leg_t *defleg;  nta_leg_t *example_net;  nta_leg_t *example_org;  nta_leg_t *example_com;  sip_contact_t *transport_contacts;  struct proxy_transaction *stateless;  struct proxy_transaction *transactions;  struct registration_entry *entries;  struct {    sip_time_t min_expires, expires, max_expires;  } prefs;}; LIST_PROTOS(static, registration_entry, struct registration_entry);static struct registration_entry *registration_entry_new(struct proxy *,							 url_t const *);static void registration_entry_destroy(struct registration_entry *e);struct registration_entry{  struct registration_entry *next, **prev;  struct proxy *proxy;		/* backpointer */  url_t *aor;			/* address-of-record */  struct binding *bindings;	/* list of bindings */  sip_contact_t *contacts;};struct binding{  struct binding *next, **prev;  sip_contact_t *contact;	/* bindings */  sip_time_t registered, expires; /* When registered and when expires */  sip_call_id_t *call_id;	  uint32_t cseq;};static struct binding *binding_new(su_home_t *home, 				   sip_contact_t *contact,				   sip_call_id_t *call_id,				   uint32_t cseq,				   sip_time_t registered, 				   sip_time_t expires);static void binding_destroy(su_home_t *home, struct binding *b);static int binding_is_active(struct binding const *b){  return b->expires > sip_now();}LIST_PROTOS(static, proxy_transaction, struct proxy_transaction);struct proxy_transaction *proxy_transaction_new(struct proxy *);static void proxy_transaction_destroy(struct proxy_transaction *t);struct proxy_transaction{  struct proxy_transaction *next, **prev;  struct proxy *proxy;		/* backpointer */  sip_request_t *rq;		/* request line */  nta_incoming_t *server;	/* server transaction */  nta_outgoing_t *client;	/* client transaction */};static sip_contact_t *create_transport_contacts(struct proxy *p);static int proxy_request(struct proxy *proxy,			 nta_leg_t *leg,			 nta_incoming_t *irq,			 sip_t const *sip);static int proxy_ack_cancel(struct proxy_transaction *t,			    nta_incoming_t *irq,			    sip_t const *sip);static int proxy_response(struct proxy_transaction *t,			  nta_outgoing_t *client,			  sip_t const *sip);static int process_register(struct proxy *proxy,			    nta_incoming_t *irq,			    sip_t const *sip);static int domain_request(struct proxy *proxy,			  nta_leg_t *leg,			  nta_incoming_t *irq,			  sip_t const *sip);static int process_options(struct proxy *proxy,			   nta_incoming_t *irq,			   sip_t const *sip);static struct registration_entry *registration_entry_find(struct proxy const *proxy, url_t const *uri);static auth_challenger_t registrar_challenger[1];static auth_challenger_t proxy_challenger[1];/* Proxy entry point */static int test_proxy_init(su_root_t *root, struct proxy *proxy){  struct proxy_transaction *t;  auth_challenger_t _proxy_challenger[1] =   {{       SIP_407_PROXY_AUTH_REQUIRED,      sip_proxy_authenticate_class,      sip_proxy_authentication_info_class    }};  auth_challenger_t _registrar_challenger[1] =   {{       SIP_401_UNAUTHORIZED,      sip_www_authenticate_class,      sip_authentication_info_class    }};  *proxy_challenger = *_proxy_challenger;  *registrar_challenger = *_registrar_challenger;  proxy->root = root;  proxy->auth = auth_mod_create(root, TAG_NEXT(proxy->tags));  proxy->agent = nta_agent_create(root,				  URL_STRING_MAKE("sip:0.0.0.0:*"),				  NULL, NULL,				  NTATAG_UA(0),				  NTATAG_SERVER_RPORT(1),				  NTATAG_CLIENT_RPORT(1),				  TAG_END());  proxy->transport_contacts = create_transport_contacts(proxy);  proxy->defleg = nta_leg_tcreate(proxy->agent,				  proxy_request,				  proxy,				  NTATAG_NO_DIALOG(1),				  TAG_END());  proxy->example_net = nta_leg_tcreate(proxy->agent,				       domain_request,				       proxy,				       NTATAG_NO_DIALOG(1),				       URLTAG_URL("sip:example.net"),				       TAG_END());  proxy->example_org = nta_leg_tcreate(proxy->agent,				       domain_request,				       proxy,				       NTATAG_NO_DIALOG(1),				       URLTAG_URL("sip:example.org"),				       TAG_END());  proxy->example_com = nta_leg_tcreate(proxy->agent,				       domain_request,				       proxy,				       NTATAG_NO_DIALOG(1),				       URLTAG_URL("sip:example.com"),				       TAG_END());  proxy->prefs.min_expires = 30;  proxy->prefs.expires = 3600;  proxy->prefs.max_expires = 3600;  if (!proxy->defleg ||       !proxy->example_net || !proxy->example_org || !proxy->example_com)    return -1;  t = su_zalloc(proxy->home, sizeof *t);   if (!t)    return -1;  proxy->stateless = t;  t->proxy = proxy;  t->server = nta_incoming_default(proxy->agent);  t->client = nta_outgoing_default(proxy->agent, proxy_response, t);  if (!t->client || !t->server)    return -1;  proxy->uri = nta_agent_contact(proxy->agent)->m_url;				    return 0;}static voidtest_proxy_deinit(su_root_t *root, struct proxy *proxy){  struct proxy_transaction *t;    auth_mod_destroy(proxy->auth);  if ((t = proxy->stateless)) {    nta_incoming_destroy(t->server), t->server = NULL;    nta_outgoing_destroy(t->client), t->client = NULL;  }  nta_agent_destroy(proxy->agent);  while (proxy->entries)    registration_entry_destroy(proxy->entries);  free(proxy->tags);}/* Create tst proxy object */struct proxy *test_proxy_create(su_root_t *root,				tag_type_t tag, tag_value_t value, ...){  struct proxy *p = su_home_new(sizeof *p);  if (p) {    ta_list ta;    p->parent = root;    ta_start(ta, tag, value);    p->tags = tl_llist(ta_tags(ta));    ta_end(ta);        if (su_clone_start(root,		       p->clone,		       p,		       test_proxy_init,		       test_proxy_deinit) == -1)      su_home_unref(p->home), p = NULL;  }  return p;}/* Destroy the proxy object */void test_proxy_destroy(struct proxy *p){  if (p) {    su_clone_wait(p->parent, p->clone);    su_home_unref(p->home);  }}/* Return the proxy URI */url_t const *test_proxy_uri(struct proxy const *p){  return p ? p->uri : NULL;}void test_proxy_set_expiration(struct proxy *p,			       sip_time_t min_expires, 			       sip_time_t expires, 			       sip_time_t max_expires){  if (p) {    p->prefs.min_expires = min_expires;    p->prefs.expires = expires;    p->prefs.max_expires = max_expires;  }}void test_proxy_get_expiration(struct proxy *p,			       sip_time_t *return_min_expires,			       sip_time_t *return_expires,			       sip_time_t *return_max_expires){  if (p) {    if (return_min_expires) *return_min_expires = p->prefs.min_expires;    if (return_expires) *return_expires = p->prefs.expires;    if (return_max_expires) *return_max_expires = p->prefs.max_expires;  }}/* ---------------------------------------------------------------------- */static sip_contact_t *create_transport_contacts(struct proxy *p){  su_home_t *home = p->home;  sip_via_t *v;  sip_contact_t *retval = NULL, **mm = &retval;  if (!p->agent)    return NULL;  for (v = nta_agent_via(p->agent); v; v = v->v_next) {    char const *proto = v->v_protocol;    if (v->v_next && 	strcasecmp(v->v_host, v->v_next->v_host) == 0 &&	str0cmp(v->v_port, v->v_next->v_port) == 0 &&	((proto == sip_transport_udp &&	  v->v_next->v_protocol == sip_transport_tcp) ||	 (proto == sip_transport_tcp &&	  v->v_next->v_protocol == sip_transport_udp)))      /* We have udp/tcp pair, insert URL without tport parameter */      *mm = sip_contact_create_from_via_with_transport(home, v, NULL, NULL);    if (*mm) mm = &(*mm)->m_next;    *mm = sip_contact_create_from_via_with_transport(home, v, NULL, proto);    if (*mm) mm = &(*mm)->m_next;  }  return retval;}/* ---------------------------------------------------------------------- */static int challenge_request(struct proxy *, nta_incoming_t *, sip_t const *);/** Forward request */staticint proxy_request(struct proxy *proxy,		  nta_leg_t *leg,		  nta_incoming_t *irq,		  sip_t const *sip){  url_t const *request_uri, *target;  struct proxy_transaction *t = NULL;  sip_request_t *rq = NULL;  sip_max_forwards_t *mf;  sip_method_t method = sip->sip_request->rq_method;  mf = sip->sip_max_forwards;  if (mf && mf->mf_count <= 1) {    if (sip->sip_request->rq_method == sip_method_options) {      return process_options(proxy, irq, sip);    }    nta_incoming_treply(irq, SIP_483_TOO_MANY_HOPS, TAG_END());    return 483;  }  if (method != sip_method_ack && method != sip_method_cancel &&       str0casecmp(sip->sip_from->a_url->url_host, "example.net") == 0) {    /* Challenge everything but CANCEL and ACK coming from Mr. C */    int status = challenge_request(proxy, irq, sip);    if (status)      return status;  }  /* We don't do any route processing */  request_uri = sip->sip_request->rq_url;  if (!request_uri->url_host ||       (strcasecmp(request_uri->url_host, "example.org") &&       strcasecmp(request_uri->url_host, "example.net") &&       strcasecmp(request_uri->url_host, "example.com"))) {    target = request_uri;  }  else {    struct registration_entry *e;    struct binding *b;    if (sip->sip_request->rq_method == sip_method_register)       return process_register(proxy, irq, sip);    e = registration_entry_find(proxy, request_uri);    if (e == NULL) {      nta_incoming_treply(irq, SIP_404_NOT_FOUND, TAG_END());      return 404;    }    for (b = e->bindings; b; b = b->next)      if (binding_is_active(b))	break;    if (b == NULL) {      nta_incoming_treply(irq, SIP_480_TEMPORARILY_UNAVAILABLE, TAG_END());      return 480;    }        target = b->contact->m_url;  }  t = proxy_transaction_new(proxy);  if (t == NULL) {    nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());    return 500;  }  nta_incoming_bind(t->server = irq, proxy_ack_cancel, t);    rq = sip_request_create(proxy->home,			  sip->sip_request->rq_method,			  sip->sip_request->rq_method_name,			  (url_string_t *)target,			  NULL);  if (rq == NULL) {    nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());    proxy_transaction_destroy(t);    return 500;  }  t->rq = rq;  /* Forward request */  t->client = nta_outgoing_mcreate(proxy->agent, proxy_response, t, NULL,				   nta_incoming_getrequest(irq),				   /* rewrite request */				   SIPTAG_REQUEST(rq),				   TAG_END());  if (t->client == NULL) {    proxy_transaction_destroy(t);    nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());    return 500;  }  else if (sip->sip_request->rq_method == sip_method_ack)    proxy_transaction_destroy(t);  return 0;}staticint challenge_request(struct proxy *p,		     nta_incoming_t *irq,		     sip_t const *sip){

⌨️ 快捷键说明

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