📄 test_nua.c
字号:
/* * 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_nua.c * @brief High-level tester for Sofia SIP User Agent Engine * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Martti Mela <Martti Mela@nokia.com> * * @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi */#include "config.h"struct context;#define NUA_MAGIC_T struct contextstruct call;#define NUA_HMAGIC_T struct call#include "sofia-sip/nua.h"#include "sofia-sip/sip_status.h"#include <sofia-sip/sdp.h>#include <sofia-sip/sip_header.h>#include <sofia-sip/su_log.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su_tag_io.h>#include <test_proxy.h>#include <test_nat.h>#include <sofia-sip/auth_module.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <unistd.h>#if HAVE_ALARM#include <signal.h>#endif#if defined(_WIN32)#include <fcntl.h>#endifextern su_log_t nua_log[];extern su_log_t soa_log[];extern su_log_t nea_log[];extern su_log_t nta_log[];extern su_log_t tport_log[];extern su_log_t su_log_default[];extern void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);char const name[] = "test_nua";int print_headings = 1;int tstflags = 0;#define TSTFLAGS tstflags#include <sofia-sip/tstdef.h>#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#else#define __func__ name#endif#define NONE ((void*)-1)#define TEST_E(a, b) TEST_S(nua_event_name(a), nua_event_name(b))struct endpoint;typedefint condition_function(nua_event_t event, int status, char const *phrase, nua_t *nua, struct context *ctx, struct endpoint *ep, nua_handle_t *nh, struct call *call, sip_t const *sip, tagi_t tags[]);typedefvoid printer_function(nua_event_t event, char const *operation, int status, char const *phrase, nua_t *nua, struct context *ctx, struct endpoint *ep, nua_handle_t *nh, struct call *call, sip_t const *sip, tagi_t tags[]);struct proxy_transaction;struct registration_entry;struct context{ su_home_t home[1]; su_root_t *root; int threading; struct endpoint { char name[4]; struct context *ctx; /* Backpointer */ int running; condition_function *next_condition; nua_event_t next_event, last_event; nua_t *nua; sip_contact_t *contact; sip_from_t *to; printer_function *printer; /* Per-call stuff */ struct call { struct call *next; nua_handle_t *nh; struct { struct event *head, **tail; } events; char const *sdp; } call[1], reg[1]; /* State flags for complex scenarios */ union { struct { unsigned bit0:1, bit1:1, bit2:1, bit3:1; unsigned bit4:1, bit5:1, bit6:1, bit7:1; } b; unsigned n; } flags; } a, b, c; struct proxy *p; struct nat *nat;};struct event{ struct event *next, **prev; nua_saved_event_t saved_event[1]; nua_event_data_t const *data;};static int save_event_in_list(struct context *, nua_event_t nevent, struct endpoint *, struct call *);static void free_events_in_list(struct context *, struct call *);#define CONDITION_PARAMS \ nua_event_t event, \ int status, char const *phrase, \ nua_t *nua, struct context *ctx, \ struct endpoint *ep, \ nua_handle_t *nh, struct call *call, \ sip_t const *sip, \ tagi_t tags[]int until_final_response(CONDITION_PARAMS){ return status >= 200; }int save_until_final_response(CONDITION_PARAMS){ save_event_in_list(ctx, event, ep, ep->call); return event >= nua_r_set_params && status >= 200;}/** Save events (except nua_i_active or terminated). * Terminate when a event is saved. */int save_until_received(CONDITION_PARAMS){ save_event_in_list(ctx, event, ep, ep->call); return 1;}/* Return call state from event tag list */int callstate(tagi_t const *tags){ tagi_t const *ti = tl_find(tags, nutag_callstate); return ti ? ti->t_value : -1;}/* Return true if offer is sent */int is_offer_sent(tagi_t const *tags){ tagi_t const *ti = tl_find(tags, nutag_offer_sent); return ti ? ti->t_value : 0;}/* Return true if answer is sent */int is_answer_sent(tagi_t const *tags){ tagi_t const *ti = tl_find(tags, nutag_answer_sent); return ti ? ti->t_value : 0;}/* Return true if offer is recv */int is_offer_recv(tagi_t const *tags){ tagi_t const *ti = tl_find(tags, nutag_offer_recv); return ti ? ti->t_value : 0;}/* Return true if answer is recv */int is_answer_recv(tagi_t const *tags){ tagi_t const *ti = tl_find(tags, nutag_answer_recv); return ti ? ti->t_value : 0;}/* Return audio state from event tag list */int audio_activity(tagi_t const *tags){ tagi_t const *ti = tl_find(tags, soatag_active_audio); return ti ? ti->t_value : -1;}/* Return video state from event tag list */int video_activity(tagi_t const *tags){ tagi_t const *ti = tl_find(tags, soatag_active_video); return ti ? ti->t_value : -1;}staticvoid print_event(nua_event_t event, char const *operation, int status, char const *phrase, nua_t *nua, struct context *ctx, struct endpoint *ep, nua_handle_t *nh, struct call *call, sip_t const *sip, tagi_t tags[]){ if (event == nua_i_state) { fprintf(stderr, "%s.nua(%p): event %s %s\n", ep->name, nh, nua_event_name(event), nua_callstate_name(callstate(tags))); } else if ((int)event >= nua_r_set_params) { fprintf(stderr, "%s.nua(%p): event %s status %u %s\n", ep->name, nh, nua_event_name(event), status, phrase); } else if ((int)event >= 0) { fprintf(stderr, "%s.nua(%p): event %s %s\n", ep->name, nh, nua_event_name(event), phrase); } else if (status > 0) { fprintf(stderr, "%s.nua(%p): call %s() with status %u %s\n", ep->name, nh, operation, status, phrase); } else { tagi_t const *t; t = tl_find(tags, siptag_subject_str); if (t && t->t_value) { char const *subject = (char const *)t->t_value; fprintf(stderr, "%s.nua(%p): call %s() \"%s\"\n", ep->name, nh, operation, subject); } else fprintf(stderr, "%s.nua(%p): call %s()\n", ep->name, nh, operation); } if ((tstflags & tst_verbatim) && tags) tl_print(stderr, "", tags);}void ep_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, struct context *ctx, struct endpoint *ep, nua_handle_t *nh, struct call *call, sip_t const *sip, tagi_t tags[]){ if (ep->printer) ep->printer(event, "", status, phrase, nua, ctx, ep, nh, call, sip, tags); if (call == NULL) { for (call = ep->call; call; call = call->next) { if (!call->nh) break; if (nh == call->nh) break; } if (call && call->nh == NULL) { call->nh = nh; nua_handle_bind(nh, call); } } if ((ep->next_event == -1 || ep->next_event == event) && (ep->next_condition == NULL || ep->next_condition(event, status, phrase, nua, ctx, ep, nh, call, sip, tags))) ep->running = 0; ep->last_event = event;}void a_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, struct context *ctx, nua_handle_t *nh, struct call *call, sip_t const *sip, tagi_t tags[]){ ep_callback(event, status, phrase, nua, ctx, &ctx->a, nh, call, sip, tags);}void b_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, struct context *ctx, nua_handle_t *nh, struct call *call, sip_t const *sip, tagi_t tags[]){ ep_callback(event, status, phrase, nua, ctx, &ctx->b, nh, call, sip, tags);}void c_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, struct context *ctx, nua_handle_t *nh, struct call *call, sip_t const *sip, tagi_t tags[]){ ep_callback(event, status, phrase, nua, ctx, &ctx->c, nh, call, sip, tags);}void run_abc_until(struct context *ctx, nua_event_t a_event, condition_function *a_condition, nua_event_t b_event, condition_function *b_condition, nua_event_t c_event, condition_function *c_condition){ struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c; a->next_event = a_event; a->next_condition = a_condition; a->last_event = -1; a->running = a_condition != NULL || a_event != -1; a->flags.n = 0; b->next_event = b_event; b->next_condition = b_condition; b->last_event = -1; b->running = b_condition != NULL || b_event != -1; b->flags.n = 0; c->next_event = c_event; c->next_condition = c_condition; c->last_event = -1; c->running = c_condition != NULL || c_event != -1; c->flags.n = 0; for (; a->running || b->running || c->running;) { su_root_step(ctx->root, 1000); }}void run_ab_until(struct context *ctx, nua_event_t a_event, condition_function *a_condition, nua_event_t b_event, condition_function *b_condition){ run_abc_until(ctx, a_event, a_condition, b_event, b_condition, -1, NULL);}int run_a_until(struct context *ctx, nua_event_t a_event, condition_function *a_condition){ run_abc_until(ctx, a_event, a_condition, -1, NULL, -1, NULL); return ctx->a.last_event;}int run_b_until(struct context *ctx, nua_event_t b_event, condition_function *b_condition){ run_abc_until(ctx, -1, NULL, b_event, b_condition, -1, NULL); return ctx->b.last_event;}int run_c_until(struct context *ctx, nua_event_t event, condition_function *condition){ run_abc_until(ctx, -1, NULL, -1, NULL, event, condition); return ctx->c.last_event;}#define OPERATION(x) \int x(struct endpoint *ep, \ struct call *call, nua_handle_t *nh, \ tag_type_t tag, tag_value_t value, \ ...) \{ \ ta_list ta; \ ta_start(ta, tag, value); \\ if (ep->printer) \ ep->printer(-1, "nua_" #x, 0, "", ep->nua, ep->ctx, ep, \ nh, call, NULL, ta_args(ta)); \\ nua_##x(nh, ta_tags(ta)); \\ ta_end(ta); \ return 0; \} extern int dummyOPERATION(invite);OPERATION(ack);OPERATION(bye);OPERATION(cancel);OPERATION(authenticate);OPERATION(update);OPERATION(info);OPERATION(refer);OPERATION(message);OPERATION(options);OPERATION(publish);OPERATION(unpublish);OPERATION(unregister);OPERATION(subscribe);OPERATION(unsubscribe);OPERATION(notify);OPERATION(notifier);OPERATION(terminate);OPERATION(authorize);int do_register(struct endpoint *ep, struct call *call, nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...){ ta_list ta; ta_start(ta, tag, value); if (ep->printer) ep->printer(-1, "nua_" "register", 0, "", ep->nua, ep->ctx, ep, nh, call, NULL, ta_args(ta)); nua_register(nh, ta_tags(ta)); ta_end(ta); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -