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

📄 test_s2.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 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 s2tester.c * @brief 2nd test Suite for Sofia SIP User Agent Engine * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Wed Apr 30 12:48:27 EEST 2008 ppessi */#include "config.h"#undef NDEBUG#define TP_MAGIC_T struct tp_magic_s#include "test_s2.h"#include <sofia-sip/sip_header.h>#include <sofia-sip/sip_status.h>#include <sofia-sip/msg_addr.h>#include <sofia-sip/su_log.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su_alloc.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <limits.h>#include <time.h>/* -- Module types ------------------------------------------------------ */struct tp_magic_s{  sip_via_t *via;  sip_contact_t *contact;};/* -- Module prototypes ------------------------------------------------- */static msg_t *s2_msg(int flags);static int s2_complete_response(msg_t *response, 				int status, char const *phrase, 				msg_t *request);static char *s2_generate_tag(su_home_t *home);/* -- Module globals ---------------------------------------------------- */struct tester *s2;static char const *_s2case = "0.0";static unsigned s2_tag_generator = 0;/* -- Globals ----------------------------------------------------------- */unsigned s2_default_registration_duration = 3600;char const s2_auth_digest_str[] =  "Digest realm=\"s2test\", "  "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "  "qop=\"auth\", "  "algorithm=\"MD5\"";char const s2_auth_credentials[] = "Digest:\"s2test\":abc:abc";char const s2_auth2_digest_str[] =  "Digest realm=\"s2test2\", "  "nonce=\"fb0c093dcd98b7102dd2f0e8b11d0f600b\", "  "qop=\"auth\", "  "algorithm=\"MD5\"";char const s2_auth2_credentials[] = "Digest:\"s2test2\":abc:abc";char const s2_auth3_digest_str[] =  "Digest realm=\"s2test3\", "  "nonce=\"e8b11d0f600bfb0c093dcd98b7102dd2f0\", "  "qop=\"auth-int\", "  "algorithm=\"MD5-sess\"";char const s2_auth3_credentials[] = "Digest:\"s2test3\":abc:abc";/* -- Delay scenarios --------------------------------------------------- */static unsigned long time_offset;extern void (*_su_time)(su_time_t *tv);static void _su_time_fast_forwarder(su_time_t *tv){  tv->tv_sec += time_offset;}void s2_fast_forward(unsigned long seconds){  if (_su_time == NULL)    _su_time = _su_time_fast_forwarder;  time_offset += seconds;}/* -- NUA events -------------------------------------------------------- */struct event *s2_remove_event(struct event *e){  if ((*e->prev = e->next))    e->next->prev = e->prev;  e->prev = NULL, e->next = NULL;  return e; }void s2_free_event(struct event *e){  if (e) {    if (e->prev) {      if ((*e->prev = e->next))	e->next->prev = e->prev;    }    nua_destroy_event(e->event);    nua_handle_unref(e->nh);    free(e);  }}void s2_flush_events(void){  while (s2->events) {    s2_free_event(s2->events);  }}struct event *s2_next_event(void){  for (;;) {    if (s2->events)      return s2_remove_event(s2->events);    su_root_step(s2->root, 100);  }} struct event *s2_wait_for_event(nua_event_t event, int status){  struct event *e;  for (;;) {    for (e = s2->events; e; e = e->next) {      if (event != nua_i_none && event != e->data->e_event)	continue;      if (status && e->data->e_status != status)	continue;      return s2_remove_event(e);    }    su_root_step(s2->root, 100);  }} int s2_check_event(nua_event_t event, int status){  struct event *e = s2_wait_for_event(event, status);  s2_free_event(e);  return e != NULL;}int s2_check_callstate(enum nua_callstate state){  int retval = 0;  tagi_t const *tagi;  struct event *e;  e = s2_wait_for_event(nua_i_state, 0);  if (e) {    tagi = tl_find(e->data->e_tags, nutag_callstate);    if (tagi) {      retval = (tag_value_t)state == tagi->t_value;    }  }  s2_free_event(e);  return retval;}static void s2_nua_callback(nua_event_t event,		int status, char const *phrase,		nua_t *nua, nua_magic_t *_t,		nua_handle_t *nh, nua_hmagic_t *hmagic,		sip_t const *sip,		tagi_t tags[]){  struct event *e, **prev;  if (event == nua_i_active || event == nua_i_terminated)    return;    e = calloc(1, sizeof *e);  nua_save_event(nua, e->event);  e->nh = nua_handle_ref(nh);  e->data = nua_event_data(e->event);  for (prev = &s2->events; *prev; prev = &(*prev)->next)    ;  *prev = e, e->prev = prev;}struct message *s2_remove_message(struct message *m){  if ((*m->prev = m->next))    m->next->prev = m->prev;  m->prev = NULL, m->next = NULL;  return m; }voids2_free_message(struct message *m){  if (m) {    if (m->prev) {      if ((*m->prev = m->next))	m->next->prev = m->prev;    }    msg_destroy(m->msg);    tport_unref(m->tport);    free(m);  }}void s2_flush_messages(void){  while (s2->received) {    s2_free_message(s2->received);  }}struct message *s2_next_response(void){  struct message *m;  for (;;) {    for (m = s2->received; m; m = m->next) {      if (m->sip->sip_status)	return s2_remove_message(m);    }    su_root_step(s2->root, 100);  }}struct message *s2_wait_for_response(int status, sip_method_t method, char const *name){  struct message *m;  for (;;) {    for (m = s2->received; m; m = m->next) {      if (!m->sip->sip_status)	continue;      if (status != 0 && m->sip->sip_status->st_status != status)	continue;      if (method == sip_method_unknown && name == NULL)	break;            if (m->sip->sip_cseq == NULL)	continue;            if (m->sip->sip_cseq->cs_method != method)	continue;      if (name == NULL)	break;      if (strcmp(m->sip->sip_cseq->cs_method_name, name) == 0)	break;    }    if (m)      return s2_remove_message(m);    su_root_step(s2->root, 100);  }} ints2_check_response(int status, sip_method_t method, char const *name){  struct message *m = s2_wait_for_response(status, method, name);  s2_free_message(m);  return m != NULL;}struct message *s2_next_request(void){  struct message *m;  for (;;) {    for (m = s2->received; m; m = m->next) {      if (m->sip->sip_request)	return s2_remove_message(m);    }    su_root_step(s2->root, 100);  }    return NULL;} struct message *s2_wait_for_request(sip_method_t method, char const *name){  struct message *m;  for (;;) {    for (m = s2->received; m; m = m->next) {      if (m->sip->sip_request) {	if (method == sip_method_unknown && name == NULL)	  return s2_remove_message(m);	if (m->sip->sip_request->rq_method == method &&	    strcmp(m->sip->sip_request->rq_method_name, name) == 0)	  return s2_remove_message(m);      }    }    su_root_step(s2->root, 100);  }    return NULL;} ints2_check_request(sip_method_t method, char const *name){  struct message *m = s2_wait_for_request(method, name);  s2_free_message(m);  return m != NULL;}struct message *s2_respond_to(struct message *m, struct dialog *d,	      int status, char const *phrase,	      tag_type_t tag, tag_value_t value, ...){  ta_list ta;  msg_t *reply;  sip_t *sip;  su_home_t *home;  tp_name_t tpn[1];  char *rport;  assert(m); assert(m->msg); assert(m->tport);  assert(100 <= status && status < 700);  ta_start(ta, tag, value);  reply = s2_msg(0); sip = sip_object(reply); home = msg_home(reply);  assert(reply && home && sip);  if (sip_add_tl(reply, sip, ta_tags(ta)) < 0) {    abort();  }  s2_complete_response(reply, status, phrase, m->msg);  if (sip->sip_status && sip->sip_status->st_status > 100 &&      sip->sip_to && !sip->sip_to->a_tag &&      sip->sip_cseq && sip->sip_cseq->cs_method != sip_method_cancel) {    char const *ltag = NULL;    if (d && d->local)      ltag = d->local->a_tag;    if (ltag == NULL)      ltag = s2_generate_tag(home);    if (sip_to_tag(msg_home(reply), sip->sip_to, ltag) < 0) {      assert(!"add To tag");    }  }  if (d && !d->local) {    d->local = sip_from_dup(d->home, sip->sip_to);    d->remote = sip_to_dup(d->home, sip->sip_from);    d->call_id = sip_call_id_dup(d->home, sip->sip_call_id);    d->rseq = sip->sip_cseq->cs_seq;    /* d->route = sip_route_dup(d->home, sip->sip_record_route); */    d->target = sip_contact_dup(d->home, m->sip->sip_contact);    d->contact = sip_contact_dup(d->home, sip->sip_contact);  }  *tpn = *tport_name(m->tport);  rport = su_sprintf(home, "rport=%u", 		     ntohs(((su_sockaddr_t *)			    msg_addrinfo(m->msg)->ai_addr)->su_port));  if (s2->server_uses_rport &&      sip->sip_via->v_rport &&      sip->sip_via->v_rport[0] == '\0') {    msg_header_add_param(home, sip->sip_via->v_common, rport);  }      tpn->tpn_port = rport + strlen("rport=");  tport_tsend(m->tport, reply, tpn, TPTAG_MTU(INT_MAX), ta_tags(ta));  msg_destroy(reply);  ta_end(ta);  return m;}/** Add headers from the request to the response message. */static int s2_complete_response(msg_t *response, 		     int status, char const *phrase, 		     msg_t *request){  su_home_t *home = msg_home(response);  sip_t *response_sip = sip_object(response);  sip_t const *request_sip = sip_object(request);  int incomplete = 0;  if (!response_sip || !request_sip || !request_sip->sip_request)    return -1;  if (!response_sip->sip_status)    response_sip->sip_status = sip_status_create(home, status, phrase, NULL);  if (!response_sip->sip_via)    response_sip->sip_via = sip_via_dup(home, request_sip->sip_via);  if (!response_sip->sip_from)    response_sip->sip_from = sip_from_dup(home, request_sip->sip_from);  if (!response_sip->sip_to)    response_sip->sip_to = sip_to_dup(home, request_sip->sip_to);  if (!response_sip->sip_call_id)    response_sip->sip_call_id =       sip_call_id_dup(home, request_sip->sip_call_id);  if (!response_sip->sip_cseq)    response_sip->sip_cseq = sip_cseq_dup(home, request_sip->sip_cseq);  if (!response_sip->sip_record_route && request_sip->sip_record_route)    sip_add_dup(response, response_sip, (void*)request_sip->sip_record_route);  incomplete = sip_complete_message(response) < 0;  msg_serialize(response, (msg_pub_t *)response_sip);  if (incomplete ||      !response_sip->sip_status ||      !response_sip->sip_via ||      !response_sip->sip_from ||      !response_sip->sip_to ||      !response_sip->sip_call_id ||      !response_sip->sip_cseq ||      !response_sip->sip_content_length ||      !response_sip->sip_separator ||      (request_sip->sip_record_route && !response_sip->sip_record_route))    return -1;  return 0;}/* Send request (updating dialog).  * * Return zero upon success, nonzero upon failure. */int s2_request_to(struct dialog *d,	      sip_method_t method, char const *name,	      tport_t *tport,	      tag_type_t tag, tag_value_t value, ...){  ta_list ta;  tagi_t const *tags;  msg_t *msg = s2_msg(0);  sip_t *sip = sip_object(msg);  url_string_t *target = NULL;  sip_cseq_t cseq[1];  sip_via_t via[1]; char const *v_params[8];  sip_content_length_t l[1];  tp_name_t tpn[1];  tp_magic_t *magic;  ta_start(ta, tag, value);  tags = ta_args(ta);  if (sip_add_tagis(msg, sip, &tags) < 0)    goto error;  if (!sip->sip_request) {    sip_request_t *rq;    if (d->target)      target = (url_string_t *)d->target->m_url;    else if (s2->registration->contact)      target = (url_string_t *)s2->registration->contact->m_url;    else      target = NULL;

⌨️ 快捷键说明

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