test_nua.c 175 KB
Newer Older
Pekka Pessi's avatar
Pekka Pessi committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * 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>
Pekka Pessi's avatar
Pekka Pessi committed
29
 * @author Martti Mela <Martti Mela@nokia.com>
Pekka Pessi's avatar
Pekka Pessi committed
30
31
32
33
34
35
36
37
 *
 * @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi
 */

#include "config.h"

struct context;
#define NUA_MAGIC_T struct context
Pekka Pessi's avatar
Pekka Pessi committed
38
39
40

struct call;
#define NUA_HMAGIC_T struct call
Pekka Pessi's avatar
Pekka Pessi committed
41

42
43
#include "sofia-sip/nua.h"
#include "sofia-sip/sip_status.h"
Pekka Pessi's avatar
Pekka Pessi committed
44

45
46
#include <sofia-sip/sdp.h>
#include <sofia-sip/sip_header.h>
Pekka Pessi's avatar
Pekka Pessi committed
47

48
49
50
#include <sofia-sip/su_log.h>
#include <sofia-sip/su_tagarg.h>
#include <sofia-sip/su_tag_io.h>
Pekka Pessi's avatar
Pekka Pessi committed
51

Pekka Pessi's avatar
Pekka Pessi committed
52
#include <test_proxy.h>
Pekka Pessi's avatar
Pekka Pessi committed
53
#include <test_nat.h>
54
#include <sofia-sip/auth_module.h>
Pekka Pessi's avatar
Pekka Pessi committed
55

56
57
58
59
60
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#include <assert.h>
61
#include <unistd.h>
62
63
64
65
66

#if HAVE_ALARM
#include <signal.h>
#endif

67
68
69
70
#if defined(_WIN32)
#include <fcntl.h>
#endif

71
72
73
74
75
76
SOFIAPUBVAR su_log_t nua_log[];
SOFIAPUBVAR su_log_t soa_log[];
SOFIAPUBVAR su_log_t nea_log[];
SOFIAPUBVAR su_log_t nta_log[];
SOFIAPUBVAR su_log_t tport_log[];
SOFIAPUBVAR su_log_t su_log_default[];
Pekka Pessi's avatar
Pekka Pessi committed
77

78
79
80
extern void *memmem(const void *haystack, size_t haystacklen,
		    const void *needle, size_t needlelen);

Pekka Pessi's avatar
Pekka Pessi committed
81
char const name[] = "test_nua";
82
83

int print_headings = 1;
Pekka Pessi's avatar
Pekka Pessi committed
84
85
86
int tstflags = 0;
#define TSTFLAGS tstflags

87
#include <sofia-sip/tstdef.h>
Pekka Pessi's avatar
Pekka Pessi committed
88
89
90
91
92
93
94
95
96
97

#if HAVE_FUNC
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
#define __func__ name
#endif

#define NONE ((void*)-1)

98
99
#define TEST_E(a, b) TEST_S(nua_event_name(a), nua_event_name(b))

100
101
102
struct endpoint;

typedef
Pekka Pessi's avatar
Pekka Pessi committed
103
104
105
int condition_function(nua_event_t event,
		       int status, char const *phrase,
		       nua_t *nua, struct context *ctx,
106
		       struct endpoint *ep,
Pekka Pessi's avatar
Pekka Pessi committed
107
		       nua_handle_t *nh, struct call *call,
Pekka Pessi's avatar
Pekka Pessi committed
108
109
110
		       sip_t const *sip,
		       tagi_t tags[]);

Pekka Pessi's avatar
Pekka Pessi committed
111
112
113
114
115
116
117
118
119
120
typedef
void 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[]);

Pekka Pessi's avatar
Pekka Pessi committed
121
122
123
struct proxy_transaction;
struct registration_entry;

124
enum { event_is_extra, event_is_normal, event_is_special };
Pekka Pessi's avatar
Pekka Pessi committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

struct eventlist {
  nua_event_t kind;
  struct event *head, **tail;
};

struct event
{
  struct event *next, **prev;
  struct call *call;
  nua_saved_event_t saved_event[1];
  nua_event_data_t const *data;
};


140
struct context
Pekka Pessi's avatar
Pekka Pessi committed
141
142
143
144
{
  su_home_t home[1];
  su_root_t *root;

145
  int threading, proxy_tests, expensive;
146
  char const *external_proxy;
Pekka Pessi's avatar
Pekka Pessi committed
147

148
  struct endpoint {
Pekka Pessi's avatar
Pekka Pessi committed
149
    char name[4];
Pekka Pessi's avatar
Pekka Pessi committed
150
    struct context *ctx;	/* Backpointer */
151
152
153

    int running;

154
155
    condition_function *next_condition;
    nua_event_t next_event, last_event;
Pekka Pessi's avatar
Pekka Pessi committed
156
    nua_t *nua;
157
    sip_contact_t *contact;
Pekka Pessi's avatar
Pekka Pessi committed
158
    sip_from_t *to;
Pekka Pessi's avatar
Pekka Pessi committed
159

Pekka Pessi's avatar
Pekka Pessi committed
160
    printer_function *printer;
Pekka Pessi's avatar
Pekka Pessi committed
161

162
163
    char const *instance;

Pekka Pessi's avatar
Pekka Pessi committed
164
    /* Per-call stuff */
Pekka Pessi's avatar
Pekka Pessi committed
165
166
167
    struct call {
      struct call *next;
      nua_handle_t *nh;
168
      char const *sdp;
Pekka Pessi's avatar
Pekka Pessi committed
169
      struct eventlist *events;
Pekka Pessi's avatar
Pekka Pessi committed
170
    } call[1], reg[1];
Pekka Pessi's avatar
Pekka Pessi committed
171

Pekka Pessi's avatar
Pekka Pessi committed
172
173
174
175
176
177
178
    int (*is_special)(nua_event_t e);

    /* Normal events are saved here */
    struct eventlist events[1];
    /* Special events are saved here */
    struct eventlist specials[1];

Pekka Pessi's avatar
Pekka Pessi committed
179
180
181
182
183
184
185
186
187
    /* 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;

188
  } a, b, c;
Pekka Pessi's avatar
Pekka Pessi committed
189
190

  struct proxy *p;
Pekka Pessi's avatar
Pekka Pessi committed
191
  struct nat *nat;
Pekka Pessi's avatar
Pekka Pessi committed
192
193
};

Pekka Pessi's avatar
Pekka Pessi committed
194
195
196
197
198
static int save_event_in_list(struct context *,
			      nua_event_t nevent,
			      struct endpoint *,
			      struct call *);
static void free_events_in_list(struct context *,
Pekka Pessi's avatar
Pekka Pessi committed
199
				struct eventlist *);
200

201
202
203
204
205
206
207
208
209
210
211
#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)
212
{
Pekka Pessi's avatar
Pekka Pessi committed
213
214
  save_event_in_list(ctx, event, ep, ep->call);
  return event >= nua_r_set_params && status >= 200;
215
216
}

217
218
/** Save events.
 *
Pekka Pessi's avatar
Pekka Pessi committed
219
220
 * Terminate when a event is saved.
 */
221
int save_until_received(CONDITION_PARAMS)
222
{
223
224
225
226
227
228
229
230
231
232
233
234
  return save_event_in_list(ctx, event, ep, ep->call) == event_is_normal;
}

int save_events(CONDITION_PARAMS)
{
  return save_event_in_list(ctx, event, ep, ep->call) == event_is_normal;
}

/** Save events until nua_i_outbound is received.  */
int save_until_special(CONDITION_PARAMS)
{
  return save_event_in_list(ctx, event, ep, ep->call) == event_is_special;
235
236
}

Pekka Pessi's avatar
Pekka Pessi committed
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/* 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;
}

Pekka Pessi's avatar
Pekka Pessi committed
286
287
288
289
290
291
292
293
294
static
void 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[])
Pekka Pessi's avatar
Pekka Pessi committed
295
296
297
{
  if (event == nua_i_state) {
    fprintf(stderr, "%s.nua(%p): event %s %s\n",
298
	    ep->name, nh, nua_event_name(event),
Pekka Pessi's avatar
Pekka Pessi committed
299
300
	    nua_callstate_name(callstate(tags)));
  }
Pekka Pessi's avatar
Pekka Pessi committed
301
  else if ((int)event >= nua_r_set_params) {
Pekka Pessi's avatar
Pekka Pessi committed
302
303
304
    fprintf(stderr, "%s.nua(%p): event %s status %u %s\n",
	    ep->name, nh, nua_event_name(event), status, phrase);
  }
Pekka Pessi's avatar
Pekka Pessi committed
305
306
307
308
  else if ((int)event >= 0) {
    fprintf(stderr, "%s.nua(%p): event %s %s\n",
	    ep->name, nh, nua_event_name(event), phrase);
  }
Pekka Pessi's avatar
Pekka Pessi committed
309
310
  else if (status > 0) {
    fprintf(stderr, "%s.nua(%p): call %s() with status %u %s\n",
311
	    ep->name, nh, operation, status, phrase);
Pekka Pessi's avatar
Pekka Pessi committed
312
313
  }
  else {
Pekka Pessi's avatar
Pekka Pessi committed
314
315
316
317
318
    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",
Pekka Pessi's avatar
Pekka Pessi committed
319
	      ep->name, nh, operation, subject);
Pekka Pessi's avatar
Pekka Pessi committed
320
321
322
    }
    else
      fprintf(stderr, "%s.nua(%p): call %s()\n",
Pekka Pessi's avatar
Pekka Pessi committed
323
	      ep->name, nh, operation);
Pekka Pessi's avatar
Pekka Pessi committed
324
325
326
327
328
  }

  if ((tstflags & tst_verbatim) && tags)
    tl_print(stderr, "", tags);
}
329

330
331
332
333
void ep_callback(nua_event_t event,
		 int status, char const *phrase,
		 nua_t *nua, struct context *ctx,
		 struct endpoint *ep,
Pekka Pessi's avatar
Pekka Pessi committed
334
		 nua_handle_t *nh, struct call *call,
335
336
		 sip_t const *sip,
		 tagi_t tags[])
337
{
Pekka Pessi's avatar
Pekka Pessi committed
338
  if (ep->printer)
Pekka Pessi's avatar
Pekka Pessi committed
339
340
    ep->printer(event, "", status, phrase, nua, ctx, ep, nh, call, sip, tags);

341
  if (call == NULL && nh) {
Pekka Pessi's avatar
Pekka Pessi committed
342
343
344
345
346
347
348
349
350
351
352
353
    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);
    }
  }
Pekka Pessi's avatar
Pekka Pessi committed
354
355
356
357
358

  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)))
359
    ep->running = 0;
360

Pekka Pessi's avatar
Pekka Pessi committed
361
  ep->last_event = event;
362
363
364

  if (call == NULL && nh)
    nua_handle_destroy(nh);
365
366
}

367
void a_callback(nua_event_t event,
368
369
		int status, char const *phrase,
		nua_t *nua, struct context *ctx,
Pekka Pessi's avatar
Pekka Pessi committed
370
		nua_handle_t *nh, struct call *call,
371
372
		sip_t const *sip,
		tagi_t tags[])
Pekka Pessi's avatar
Pekka Pessi committed
373
{
374
375
  ep_callback(event, status, phrase, nua, ctx, &ctx->a, nh, call, sip, tags);
}
376

377
378
379
void b_callback(nua_event_t event,
		int status, char const *phrase,
		nua_t *nua, struct context *ctx,
Pekka Pessi's avatar
Pekka Pessi committed
380
		nua_handle_t *nh, struct call *call,
381
382
383
384
385
		sip_t const *sip,
		tagi_t tags[])
{
  ep_callback(event, status, phrase, nua, ctx, &ctx->b, nh, call, sip, tags);
}
Pekka Pessi's avatar
Pekka Pessi committed
386

387
388
389
void c_callback(nua_event_t event,
		int status, char const *phrase,
		nua_t *nua, struct context *ctx,
Pekka Pessi's avatar
Pekka Pessi committed
390
		nua_handle_t *nh, struct call *call,
391
392
393
394
		sip_t const *sip,
		tagi_t tags[])
{
  ep_callback(event, status, phrase, nua, ctx, &ctx->c, nh, call, sip, tags);
Pekka Pessi's avatar
Pekka Pessi committed
395
396
}

397
398
399
400
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)
Pekka Pessi's avatar
Pekka Pessi committed
401
{
402
  struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c;
403
404
405
406
407

  a->next_event = a_event;
  a->next_condition = a_condition;
  a->last_event = -1;
  a->running = a_condition != NULL || a_event != -1;
Pekka Pessi's avatar
Pekka Pessi committed
408
  a->flags.n = 0;
409
410
411
412
413

  b->next_event = b_event;
  b->next_condition = b_condition;
  b->last_event = -1;
  b->running = b_condition != NULL || b_event != -1;
Pekka Pessi's avatar
Pekka Pessi committed
414
  b->flags.n = 0;
Pekka Pessi's avatar
Pekka Pessi committed
415

416
417
418
419
  c->next_event = c_event;
  c->next_condition = c_condition;
  c->last_event = -1;
  c->running = c_condition != NULL || c_event != -1;
Pekka Pessi's avatar
Pekka Pessi committed
420
  c->flags.n = 0;
421
422

  for (; a->running || b->running || c->running;) {
Pekka Pessi's avatar
Pekka Pessi committed
423
424
    su_root_step(ctx->root, 1000);
  }
425
}
Pekka Pessi's avatar
Pekka Pessi committed
426

427
428
429
430
431
432
433
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);
}

434
435
436
437
int run_a_until(struct context *ctx,
		nua_event_t a_event,
		condition_function *a_condition)
{
438
  run_abc_until(ctx, a_event, a_condition, -1, NULL, -1, NULL);
439
440
441
442
443
444
445
  return ctx->a.last_event;
}

int run_b_until(struct context *ctx,
		nua_event_t b_event,
		condition_function *b_condition)
{
446
  run_abc_until(ctx, -1, NULL, b_event, b_condition, -1, NULL);
447
  return ctx->b.last_event;
Pekka Pessi's avatar
Pekka Pessi committed
448
449
}

Pekka Pessi's avatar
Pekka Pessi committed
450
451
452
453
454
455
456
457
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;
}

458
459
#define OPERATION(X, x)	   \
int X(struct endpoint *ep, \
Pekka Pessi's avatar
Pekka Pessi committed
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
      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 dummy

477
478
479
480
481
482
483
OPERATION(INVITE, invite);
OPERATION(ACK, ack);
OPERATION(BYE, bye);
OPERATION(CANCEL, cancel);
OPERATION(AUTHENTICATE, authenticate);
OPERATION(UPDATE, update);
OPERATION(INFO, info);
484
OPERATION(PRACK, prack);
485
486
487
488
489
490
491
492
493
494
495
496
497
OPERATION(REFER, refer);
OPERATION(MESSAGE, message);
OPERATION(OPTIONS, options);
OPERATION(PUBLISH, publish);
OPERATION(UNPUBLISH, unpublish);
OPERATION(REGISTER, register);
OPERATION(UNREGISTER, unregister);
OPERATION(SUBSCRIBE, subscribe);
OPERATION(UNSUBSCRIBE, unsubscribe);
OPERATION(NOTIFY, notify);
OPERATION(NOTIFIER, notifier);
OPERATION(TERMINATE, terminate);
OPERATION(AUTHORIZE, authorize);
498

Pekka Pessi's avatar
Pekka Pessi committed
499
/* Respond via endpoint and handle */
500
int RESPOND(struct endpoint *ep,
Pekka Pessi's avatar
Pekka Pessi committed
501
502
	    struct call *call,
	    nua_handle_t *nh,
Pekka Pessi's avatar
Pekka Pessi committed
503
504
505
506
507
508
509
	    int status, char const *phrase,
	    tag_type_t tag, tag_value_t value,
	    ...)
{
  ta_list ta;

  ta_start(ta, tag, value);
Pekka Pessi's avatar
Pekka Pessi committed
510
511

  if (ep->printer)
Pekka Pessi's avatar
Pekka Pessi committed
512
513
    ep->printer(-1, "nua_respond", status, phrase, ep->nua, ep->ctx, ep,
		nh, call, NULL, ta_args(ta));
Pekka Pessi's avatar
Pekka Pessi committed
514

Pekka Pessi's avatar
Pekka Pessi committed
515
516
517
518
519
520
  nua_respond(nh, status, phrase, ta_tags(ta));
  ta_end(ta);

  return 0;
}

521

Pekka Pessi's avatar
Pekka Pessi committed
522
523
524
525
526
/* Reject all but currently used handles */
struct call *check_handle(struct endpoint *ep,
			  struct call *call,
			  nua_handle_t *nh,
			  int status, char const *phrase)
527
{
Pekka Pessi's avatar
Pekka Pessi committed
528
529
  if (call)
    return call;
530

Pekka Pessi's avatar
Pekka Pessi committed
531
  if (status)
532
    RESPOND(ep, call, nh, status, phrase, TAG_END());
533

Pekka Pessi's avatar
Pekka Pessi committed
534
535
  nua_handle_destroy(nh);
  return NULL;
536
537
}

Pekka Pessi's avatar
Pekka Pessi committed
538

Pekka Pessi's avatar
Pekka Pessi committed
539
/* Save nua event in call-specific list */
540
static
541
int save_event_in_list(struct context *ctx,
Pekka Pessi's avatar
Pekka Pessi committed
542
543
544
545
		       nua_event_t nevent,
		       struct endpoint *ep,
		       struct call *call)

546
{
Pekka Pessi's avatar
Pekka Pessi committed
547
  struct eventlist *list;
Pekka Pessi's avatar
Pekka Pessi committed
548
  struct event *e;
Pekka Pessi's avatar
Pekka Pessi committed
549
  int action = ep->is_special(nevent);
Pekka Pessi's avatar
Pekka Pessi committed
550

Pekka Pessi's avatar
Pekka Pessi committed
551
  if (action == event_is_extra)
Pekka Pessi's avatar
Pekka Pessi committed
552
    return 0;
Pekka Pessi's avatar
Pekka Pessi committed
553
  else if (action == event_is_special || call == NULL)
Pekka Pessi's avatar
Pekka Pessi committed
554
555
556
557
558
    list = ep->specials;
  else if (call->events)
    list = call->events;
  else
    list = ep->events;
Pekka Pessi's avatar
Pekka Pessi committed
559
560

  e = su_zalloc(ctx->home, sizeof *e);
561
562

  if (!e) { perror("su_zalloc"), abort(); }
563

564
565
  if (!nua_save_event(ep->nua, e->saved_event)) {
    su_free(ctx->home, e);
Pekka Pessi's avatar
Pekka Pessi committed
566
    return -1;
567
  }
Pekka Pessi's avatar
Pekka Pessi committed
568

Pekka Pessi's avatar
Pekka Pessi committed
569
570
571
  *(e->prev = list->tail) = e; list->tail = &e->next;

  e->call = call;
Pekka Pessi's avatar
Pekka Pessi committed
572
  e->data = nua_event_data(e->saved_event);
573

574
  return action;
575
}
Pekka Pessi's avatar
Pekka Pessi committed
576

Pekka Pessi's avatar
Pekka Pessi committed
577
/* Save nua event in endpoint list */
578
static
Pekka Pessi's avatar
Pekka Pessi committed
579
void free_events_in_list(struct context *ctx,
Pekka Pessi's avatar
Pekka Pessi committed
580
			 struct eventlist *list)
Pekka Pessi's avatar
Pekka Pessi committed
581
582
583
{
  struct event *e;

Pekka Pessi's avatar
Pekka Pessi committed
584
  while ((e = list->head)) {
Pekka Pessi's avatar
Pekka Pessi committed
585
586
587
588
589
    if ((*e->prev = e->next))
      e->next->prev = e->prev;
    nua_destroy_event(e->saved_event);
    su_free(ctx->home, e);
  }
Pekka Pessi's avatar
Pekka Pessi committed
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

  list->tail = &list->head;
}

static
int is_special(nua_event_t e)
{
  if (e == nua_i_active || e == nua_i_terminated)
    return event_is_extra;
  if (e == nua_i_outbound)
    return event_is_special;

  return event_is_normal;
}

static void
eventlist_init(struct eventlist *list)
{
  list->tail = &list->head;
}

static void
call_init(struct call *call)
{
}

static void
endpoint_init(struct context *ctx, struct endpoint *e, char id)
{
  e->name[0] = id;
  e->ctx = ctx;

  e->is_special = is_special;

  call_init(e->call);
  call_init(e->reg);
  eventlist_init(e->events);
  eventlist_init(e->specials);
Pekka Pessi's avatar
Pekka Pessi committed
628
629
}

Pekka Pessi's avatar
Pekka Pessi committed
630
631
void nolog(void *stream, char const *fmt, va_list ap) {}

Pekka Pessi's avatar
Pekka Pessi committed
632
633
634
635
636
int check_set_status(int status, char const *phrase)
{
  return status == 200 && strcmp(phrase, sip_200_OK) == 0;
}

Pekka Pessi's avatar
Pekka Pessi committed
637
int test_nua_api_errors(struct context *ctx)
Pekka Pessi's avatar
Pekka Pessi committed
638
639
640
{
  BEGIN();

Pekka Pessi's avatar
Pekka Pessi committed
641
  /* Invoke every API function with invalid arguments */
Pekka Pessi's avatar
Pekka Pessi committed
642

Pekka Pessi's avatar
Pekka Pessi committed
643
644
  int level;

Pekka Pessi's avatar
Pekka Pessi committed
645
646
  int status; char const *phrase;

647
648
649
  if (print_headings)
    printf("TEST NUA-1.0: test API\n");

Pekka Pessi's avatar
Pekka Pessi committed
650
651
652
653
654
  /* This is a nasty macro. Test it. */
#define SET_STATUS1(x) ((status = x), status), (phrase = ((void)x))
  TEST_1(check_set_status(SET_STATUS1(SIP_200_OK)));
  TEST(status, 200); TEST_S(phrase, sip_200_OK);

Pekka Pessi's avatar
Pekka Pessi committed
655
656
657
658
659
  su_log_init(nua_log);

  level = nua_log->log_level;
  if (!(tstflags & tst_verbatim))
    su_log_set_level(nua_log, 0);
Pekka Pessi's avatar
Pekka Pessi committed
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

  TEST_1(!nua_create(NULL, NULL, NULL, TAG_END()));
  TEST_VOID(nua_shutdown(NULL));
  TEST_VOID(nua_destroy(NULL));
  TEST_VOID(nua_set_params(NULL, TAG_END()));
  TEST_VOID(nua_get_params(NULL, TAG_END()));
  TEST_1(!nua_default(NULL));
  TEST_1(!nua_handle(NULL, NULL, TAG_END()));
  TEST_VOID(nua_handle_destroy(NULL));
  TEST_VOID(nua_handle_bind(NULL, NULL));
  TEST_1(!nua_handle_has_invite(NULL));
  TEST_1(!nua_handle_has_subscribe(NULL));
  TEST_1(!nua_handle_has_register(NULL));
  TEST_1(!nua_handle_has_active_call(NULL));
  TEST_1(!nua_handle_has_call_on_hold(NULL));
  TEST_1(!nua_handle_has_events(NULL));
  TEST_1(!nua_handle_has_registrations(NULL));
  TEST_1(!nua_handle_remote(NULL));
  TEST_1(!nua_handle_local(NULL));
  TEST_S(nua_event_name(-1), "NUA_UNKNOWN");
  TEST_VOID(nua_register(NULL, TAG_END()));
  TEST_VOID(nua_unregister(NULL, TAG_END()));
  TEST_VOID(nua_invite(NULL, TAG_END()));
  TEST_VOID(nua_ack(NULL, TAG_END()));
684
  TEST_VOID(nua_prack(NULL, TAG_END()));
Pekka Pessi's avatar
Pekka Pessi committed
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
  TEST_VOID(nua_options(NULL, TAG_END()));
  TEST_VOID(nua_publish(NULL, TAG_END()));
  TEST_VOID(nua_message(NULL, TAG_END()));
  TEST_VOID(nua_chat(NULL, TAG_END()));
  TEST_VOID(nua_info(NULL, TAG_END()));
  TEST_VOID(nua_subscribe(NULL, TAG_END()));
  TEST_VOID(nua_unsubscribe(NULL, TAG_END()));
  TEST_VOID(nua_notify(NULL, TAG_END()));
  TEST_VOID(nua_notifier(NULL, TAG_END()));
  TEST_VOID(nua_terminate(NULL, TAG_END()));
  TEST_VOID(nua_refer(NULL, TAG_END()));
  TEST_VOID(nua_update(NULL, TAG_END()));
  TEST_VOID(nua_bye(NULL, TAG_END()));
  TEST_VOID(nua_cancel(NULL, TAG_END()));
  TEST_VOID(nua_authenticate(NULL, TAG_END()));
  TEST_VOID(nua_redirect(NULL, TAG_END()));
  TEST_VOID(nua_respond(NULL, 0, "", TAG_END()));
Pekka Pessi's avatar
Pekka Pessi committed
702

Pekka Pessi's avatar
Pekka Pessi committed
703
704
  TEST_1(!nua_handle_home(NULL));
  TEST_1(!nua_save_event(NULL, NULL));
705
  TEST_1(!nua_event_data(NULL));
Pekka Pessi's avatar
Pekka Pessi committed
706
  TEST_VOID(nua_destroy_event(NULL));
707

Pekka Pessi's avatar
Pekka Pessi committed
708
709
710
711
  {
    nua_saved_event_t event[1];

    memset(event, 0, sizeof event);
712

Pekka Pessi's avatar
Pekka Pessi committed
713
    TEST_1(!nua_save_event(NULL, event));
714
    TEST_1(!nua_event_data(event));
Pekka Pessi's avatar
Pekka Pessi committed
715
716
717
    TEST_VOID(nua_destroy_event(event));
  }

Pekka Pessi's avatar
Pekka Pessi committed
718
  su_log_set_level(nua_log, level);
Pekka Pessi's avatar
Pekka Pessi committed
719

720
721
722
  if (print_headings)
    printf("TEST NUA-1.0: PASSED\n");

Pekka Pessi's avatar
Pekka Pessi committed
723
724
725
  END();
}

726
#include <sofia-sip/su_tag_class.h>
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

int test_tag_filter(void)
{
  BEGIN();

#undef TAG_NAMESPACE
#define TAG_NAMESPACE "test"
  tag_typedef_t tag_a = STRTAG_TYPEDEF(a);
#define TAG_A(s)      tag_a, tag_str_v((s))
  tag_typedef_t tag_b = STRTAG_TYPEDEF(b);
#define TAG_B(s)      tag_b, tag_str_v((s))

  tagi_t filter[2] = {{ NUTAG_ANY() }, { TAG_END() }};

  tagi_t *lst, *result;

  lst = tl_list(TAG_A("X"),
Pekka Pessi's avatar
Pekka Pessi committed
744
		TAG_SKIP(2),
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
		NUTAG_URL((void *)"urn:foo"),
		TAG_B("Y"),
		NUTAG_URL((void *)"urn:bar"),
		TAG_NULL());

  TEST_1(lst);

  result = tl_afilter(NULL, filter, lst);

  TEST_1(result);
  TEST(result[0].t_tag, nutag_url);
  TEST(result[1].t_tag, nutag_url);

  tl_vfree(lst);
  free(result);

  END();
}

Pekka Pessi's avatar
Pekka Pessi committed
764
int test_nua_params(struct context *ctx)
Pekka Pessi's avatar
Pekka Pessi committed
765
766
{
  BEGIN();
767
768
769
770
771
772
773
774

  char const Alice[] = "Alice <sip:a@wonderland.org>";
  sip_from_t const *from;
  su_home_t tmphome[SU_HOME_AUTO_SIZE(16384)];
  nua_handle_t *nh;

  su_home_auto(tmphome, sizeof(tmphome));

775
  if (print_headings)
776
    printf("TEST NUA-1.1: PARAMETERS\n");
777

Pekka Pessi's avatar
Pekka Pessi committed
778
  ctx->root = su_root_create(NULL); TEST_1(ctx->root);
779

Pekka Pessi's avatar
Pekka Pessi committed
780
  /* Disable threading by command line switch? */
Pekka Pessi's avatar
Pekka Pessi committed
781
  su_root_threading(ctx->root, ctx->threading);
Pekka Pessi's avatar
Pekka Pessi committed
782

783
784
  ctx->a.nua = nua_create(ctx->root, a_callback, ctx,
			  SIPTAG_FROM_STR("sip:alice@example.com"),
785
			  NUTAG_URL("sip:0.0.0.0:*;transport=udp"),
786
			  TAG_END());
787

788
789
  TEST_1(ctx->a.nua);

790
791
792
793
794
795
  nh = nua_handle(ctx->a.nua, NULL, TAG_END()); TEST_1(nh);
  nua_handle_unref(nh);

  nh = nua_handle(ctx->a.nua, NULL, TAG_END()); TEST_1(nh);
  nua_handle_destroy(nh);

796
  from = sip_from_make(tmphome, Alice);
797
798
799

  nh = nua_handle(ctx->a.nua, NULL, TAG_END());

800
  nua_set_hparams(nh, NUTAG_INVITE_TIMER(90), TAG_END());
801
  run_a_until(ctx, nua_r_set_params, until_final_response);
802

803
804
805
806
807
808
809
810
811
812
813
814
815
816
  /* Modify all pointer values */
  nua_set_params(ctx->a.nua,
		 SIPTAG_FROM_STR(Alice),

		 SIPTAG_SUPPORTED_STR("test"),
		 SIPTAG_ALLOW_STR("DWIM, OPTIONS, INFO"),
		 SIPTAG_USER_AGENT_STR("test_nua/1.0"),

		 SIPTAG_ORGANIZATION_STR("Te-Ras y.r."),

		 NUTAG_REGISTRAR("sip:openlaboratory.net"),

		 TAG_END());

817
  run_a_until(ctx, nua_r_set_params, until_final_response);
818

819
820
821
  /* Modify everything from their default value */
  nua_set_params(ctx->a.nua,
		 SIPTAG_FROM(from),
822
		 NUTAG_RETRY_COUNT(9),
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
		 NUTAG_MAX_SUBSCRIPTIONS(6),

		 NUTAG_ENABLEINVITE(0),
		 NUTAG_AUTOALERT(1),
		 NUTAG_EARLY_MEDIA(1),
		 NUTAG_AUTOANSWER(1),
		 NUTAG_AUTOACK(0),
		 NUTAG_INVITE_TIMER(60),

		 NUTAG_SESSION_TIMER(600),
		 NUTAG_MIN_SE(35),
		 NUTAG_SESSION_REFRESHER(nua_remote_refresher),
		 NUTAG_UPDATE_REFRESH(1),

		 NUTAG_ENABLEMESSAGE(0),
		 NUTAG_ENABLEMESSENGER(1),
		 /* NUTAG_MESSAGE_AUTOANSWER(0), */

		 NUTAG_CALLEE_CAPS(1),
		 NUTAG_MEDIA_FEATURES(1),
		 NUTAG_SERVICE_ROUTE_ENABLE(0),
		 NUTAG_PATH_ENABLE(0),
845
		 NUTAG_SUBSTATE(nua_substate_pending),
846

847
848
849
850
851
852
		 NUTAG_KEEPALIVE(66),
		 NUTAG_KEEPALIVE_STREAM(33),

		 NUTAG_OUTBOUND("foo"),
		 NUTAG_INSTANCE("urn:uuid:97701ad9-39df-1229-1083-dbc0a85f029c"),

853
854
855
		 SIPTAG_SUPPORTED(sip_supported_make(tmphome, "humppaa,kuole")),
		 SIPTAG_ALLOW(sip_allow_make(tmphome, "OPTIONS, INFO")),
		 SIPTAG_USER_AGENT(sip_user_agent_make(tmphome, "test_nua")),
856

857
		 SIPTAG_ORGANIZATION(sip_organization_make(tmphome, "Pussy Galore's Flying Circus")),
858
859

		 NUTAG_MEDIA_ENABLE(0),
860
		 NUTAG_REGISTRAR(url_hdup(tmphome, (url_t *)"sip:sip.wonderland.org")),
861

862
863
		 TAG_END());

864
  run_a_until(ctx, nua_r_set_params, until_final_response);
865

866
867
868
869
  /* Modify something... */
  nua_set_params(ctx->a.nua,
		 NUTAG_RETRY_COUNT(5),
		 TAG_END());
870
  run_a_until(ctx, nua_r_set_params, until_final_response);
871
872
873
874
875

  {
    sip_from_t const *from = NONE;
    char const *from_str = "NONE";

Pekka Pessi's avatar
Pekka Pessi committed
876
877
    unsigned retry_count = -1;
    unsigned max_subscriptions = -1;
878

879
880
881
882
883
    int invite_enable = -1;
    int auto_alert = -1;
    int early_media = -1;
    int auto_answer = -1;
    int auto_ack = -1;
Pekka Pessi's avatar
Pekka Pessi committed
884
    unsigned invite_timeout = -1;
885

Pekka Pessi's avatar
Pekka Pessi committed
886
887
    unsigned session_timer = -1;
    unsigned min_se = -1;
888
889
    int refresher = -1;
    int update_refresh = -1;
890

891
892
893
    int message_enable = -1;
    int win_messenger_enable = -1;
    int message_auto_respond = -1;
894

895
896
897
898
    int callee_caps = -1;
    int media_features = -1;
    int service_route_enable = -1;
    int path_enable = -1;
899
    int substate = -1;
900
901

    sip_allow_t const *allow = NONE;
902
    char const *allow_str = "NONE";
903
904
905
906
907
908
909
    sip_supported_t const *supported = NONE;
    char const *supported_str = "NONE";
    sip_user_agent_t const *user_agent = NONE;
    char const *user_agent_str = "NONE";
    sip_organization_t const *organization = NONE;
    char const *organization_str = "NONE";

910
911
912
913
914
    char const *outbound = "NONE";
    char const *instance = "NONE";
    
    unsigned keepalive = -1, keepalive_stream = -1;

915
916
917
    url_string_t const *registrar = NONE;

    int n;
918
    struct event *e;
919

Pekka Pessi's avatar
Pekka Pessi committed
920
    nua_get_params(ctx->a.nua, TAG_ANY(), TAG_END());
921
    run_a_until(ctx, nua_r_get_params, save_until_final_response);
922

Pekka Pessi's avatar
Pekka Pessi committed
923
    TEST_1(e = ctx->a.events->head);
924
    TEST_E(e->data->e_event, nua_r_get_params);
925

926
    n = tl_gets(e->data->e_tags,
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
	       	SIPTAG_FROM_REF(from),
	       	SIPTAG_FROM_STR_REF(from_str),

	       	NUTAG_RETRY_COUNT_REF(retry_count),
	       	NUTAG_MAX_SUBSCRIPTIONS_REF(max_subscriptions),

	       	NUTAG_ENABLEINVITE_REF(invite_enable),
	       	NUTAG_AUTOALERT_REF(auto_alert),
	       	NUTAG_EARLY_MEDIA_REF(early_media),
	       	NUTAG_AUTOANSWER_REF(auto_answer),
	       	NUTAG_AUTOACK_REF(auto_ack),
	       	NUTAG_INVITE_TIMER_REF(invite_timeout),

	       	NUTAG_SESSION_TIMER_REF(session_timer),
	       	NUTAG_MIN_SE_REF(min_se),
	       	NUTAG_SESSION_REFRESHER_REF(refresher),
	       	NUTAG_UPDATE_REFRESH_REF(update_refresh),

	       	NUTAG_ENABLEMESSAGE_REF(message_enable),
	       	NUTAG_ENABLEMESSENGER_REF(win_messenger_enable),
	       	/* NUTAG_MESSAGE_AUTOANSWER(message_auto_respond), */

	       	NUTAG_CALLEE_CAPS_REF(callee_caps),
	       	NUTAG_MEDIA_FEATURES_REF(media_features),
	       	NUTAG_SERVICE_ROUTE_ENABLE_REF(service_route_enable),
	       	NUTAG_PATH_ENABLE_REF(path_enable),
953
	       	NUTAG_SUBSTATE_REF(substate),
954
955
956
957
958
959
960
961
962
963
964

	       	SIPTAG_SUPPORTED_REF(supported),
	       	SIPTAG_SUPPORTED_STR_REF(supported_str),
	       	SIPTAG_ALLOW_REF(allow),
	       	SIPTAG_ALLOW_STR_REF(allow_str),
	       	SIPTAG_USER_AGENT_REF(user_agent),
	       	SIPTAG_USER_AGENT_STR_REF(user_agent_str),

	       	SIPTAG_ORGANIZATION_REF(organization),
	       	SIPTAG_ORGANIZATION_STR_REF(organization_str),

965
966
967
968
969
970
		NUTAG_OUTBOUND_REF(outbound),
		NUTAG_INSTANCE_REF(instance),

		NUTAG_KEEPALIVE_REF(keepalive),
		NUTAG_KEEPALIVE_STREAM_REF(keepalive_stream),

971
972
973
	       	NUTAG_REGISTRAR_REF(registrar),

		TAG_END());
974
    TEST(n, 34);
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001

    TEST_S(sip_header_as_string(tmphome, (void *)from), Alice);
    TEST_S(from_str, Alice);

    TEST(retry_count, 5);
    TEST(max_subscriptions, 6);

    TEST(invite_enable, 0);
    TEST(auto_alert, 1);
    TEST(early_media, 1);
    TEST(auto_answer, 1);
    TEST(auto_ack, 0);
    TEST(invite_timeout, 60);

    TEST(session_timer, 600);
    TEST(min_se, 35);
    TEST(refresher, nua_remote_refresher);
    TEST(update_refresh, 1);

    TEST(message_enable, 0);
    TEST(win_messenger_enable, 1);
    TEST(message_auto_respond, -1); /* XXX */

    TEST(callee_caps, 1);
    TEST(media_features, 1);
    TEST(service_route_enable, 0);
    TEST(path_enable, 0);
1002
    TEST(substate, nua_substate_pending);
1003
1004
1005
1006
1007
1008
1009

    TEST_S(sip_header_as_string(tmphome, (void *)allow), "OPTIONS, INFO");
    TEST_S(allow_str, "OPTIONS, INFO");
    TEST_S(sip_header_as_string(tmphome, (void *)supported), "humppaa, kuole");
    TEST_S(supported_str, "humppaa, kuole");
    TEST_S(sip_header_as_string(tmphome, (void *)user_agent), "test_nua");
    TEST_S(user_agent_str, "test_nua");
1010
    TEST_S(sip_header_as_string(tmphome, (void *)organization),
1011
1012
1013
	   "Pussy Galore's Flying Circus");
    TEST_S(organization_str, "Pussy Galore's Flying Circus");

1014
1015
1016
1017
1018
1019
    TEST(keepalive, 66);
    TEST(keepalive_stream, 33);

    TEST_S(outbound, "foo");
    TEST_S(instance, "urn:uuid:97701ad9-39df-1229-1083-dbc0a85f029c");

1020
    TEST_S(url_as_string(tmphome, registrar->us_url),
1021
	   "sip:sip.wonderland.org");
1022

Pekka Pessi's avatar
Pekka Pessi committed
1023
    free_events_in_list(ctx, ctx->a.events);
1024
  }
1025

1026
1027
  /* Test that only those tags that have been set per handle are returned by nua_get_hparams() */

1028
1029
1030
1031
  {
    sip_from_t const *from = NONE;
    char const *from_str = "NONE";

Pekka Pessi's avatar
Pekka Pessi committed
1032
1033
    unsigned retry_count = -1;
    unsigned max_subscriptions = -1;
1034

1035
1036
1037
1038
1039
    int invite_enable = -1;
    int auto_alert = -1;
    int early_media = -1;
    int auto_answer = -1;
    int auto_ack = -1;
Pekka Pessi's avatar
Pekka Pessi committed
1040
    unsigned invite_timeout = -1;
1041

Pekka Pessi's avatar
Pekka Pessi committed
1042
1043
    unsigned session_timer = -1;
    unsigned min_se = -1;
1044
1045
    int refresher = -1;
    int update_refresh = -1;
1046

1047
1048
1049
    int message_enable = -1;
    int win_messenger_enable = -1;
    int message_auto_respond = -1;
1050

1051
1052
1053
1054
    int callee_caps = -1;
    int media_features = -1;
    int service_route_enable = -1;
    int path_enable = -1;
1055
    int substate = -1;
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068

    sip_allow_t const *allow = NONE;
    char const   *allow_str = "NONE";
    sip_supported_t const *supported = NONE;
    char const *supported_str = "NONE";
    sip_user_agent_t const *user_agent = NONE;
    char const *user_agent_str = "NONE";
    sip_organization_t const *organization = NONE;
    char const *organization_str = "NONE";

    url_string_t const *registrar = NONE;

    int n;
1069
    struct event *e;
1070

1071
    nua_get_hparams(nh, TAG_ANY(), TAG_END());
1072
    run_a_until(ctx, nua_r_get_params, save_until_final_response);
1073

Pekka Pessi's avatar
Pekka Pessi committed
1074
    TEST_1(e = ctx->a.events->head);
1075
    TEST_E(e->data->e_event, nua_r_get_params);
1076

1077
    n = tl_gets(e->data->e_tags,
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
	       	SIPTAG_FROM_REF(from),
	       	SIPTAG_FROM_STR_REF(from_str),

	       	NUTAG_RETRY_COUNT_REF(retry_count),
	       	NUTAG_MAX_SUBSCRIPTIONS_REF(max_subscriptions),

	       	NUTAG_ENABLEINVITE_REF(invite_enable),
	       	NUTAG_AUTOALERT_REF(auto_alert),
	       	NUTAG_EARLY_MEDIA_REF(early_media),
	       	NUTAG_AUTOANSWER_REF(auto_answer),
	       	NUTAG_AUTOACK_REF(auto_ack),
	       	NUTAG_INVITE_TIMER_REF(invite_timeout),

	       	NUTAG_SESSION_TIMER_REF(session_timer),
	       	NUTAG_MIN_SE_REF(min_se),
	       	NUTAG_SESSION_REFRESHER_REF(refresher),
	       	NUTAG_UPDATE_REFRESH_REF(update_refresh),

	       	NUTAG_ENABLEMESSAGE_REF(message_enable),
	       	NUTAG_ENABLEMESSENGER_REF(win_messenger_enable),
	       	/* NUTAG_MESSAGE_AUTOANSWER(message_auto_respond), */

	       	NUTAG_CALLEE_CAPS_REF(callee_caps),
	       	NUTAG_MEDIA_FEATURES_REF(media_features),
	       	NUTAG_SERVICE_ROUTE_ENABLE_REF(service_route_enable),
	       	NUTAG_PATH_ENABLE_REF(path_enable),
1104
	       	NUTAG_SUBSTATE_REF(substate),
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

	       	SIPTAG_SUPPORTED_REF(supported),
	       	SIPTAG_SUPPORTED_STR_REF(supported_str),
	       	SIPTAG_ALLOW_REF(allow),
	       	SIPTAG_ALLOW_STR_REF(allow_str),
	       	SIPTAG_USER_AGENT_REF(user_agent),
	       	SIPTAG_USER_AGENT_STR_REF(user_agent_str),

	       	SIPTAG_ORGANIZATION_REF(organization),
	       	SIPTAG_ORGANIZATION_STR_REF(organization_str),

	       	NUTAG_REGISTRAR_REF(registrar),

		TAG_END());
1119
    TEST(n, 3);
1120
1121
1122

    TEST(invite_timeout, 90);

1123
1124
    TEST_1(from != NULL && from != NONE);
    TEST_1(strcmp(from_str, "NONE"));
1125

1126
    /* Nothing else should be set */
1127
1128
    TEST(retry_count, (unsigned)-1);
    TEST(max_subscriptions, (unsigned)-1);
1129
1130
1131
1132
1133
1134
1135

    TEST(invite_enable, -1);
    TEST(auto_alert, -1);
    TEST(early_media, -1);
    TEST(auto_answer, -1);
    TEST(auto_ack, -1);

1136
1137
    TEST(session_timer, (unsigned)-1);
    TEST(min_se, (unsigned)-1);
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
    TEST(refresher, -1);
    TEST(update_refresh, -1);

    TEST(message_enable, -1);
    TEST(win_messenger_enable, -1);
    TEST(message_auto_respond, -1); /* XXX */

    TEST(callee_caps, -1);
    TEST(media_features, -1);
    TEST(service_route_enable, -1);
    TEST(path_enable, -1);
1149
    TEST(substate, -1);
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160

    TEST(allow, NONE);
    TEST_S(allow_str, "NONE");
    TEST(supported, NONE);
    TEST_S(supported_str, "NONE");
    TEST(user_agent, NONE);
    TEST_S(user_agent_str, "NONE");
    TEST(organization, NONE);
    TEST_S(organization_str, "NONE");

    TEST(registrar->us_url, NONE);
Pekka Pessi's avatar
Pekka Pessi committed
1161

Pekka Pessi's avatar
Pekka Pessi committed
1162
    free_events_in_list(ctx, ctx->a.events);
1163
1164
1165
  }

  nua_handle_destroy(nh);
1166

1167
  nua_shutdown(ctx->a.nua);
1168
  run_a_until(ctx, nua_r_shutdown, until_final_response);
1169
1170
1171
1172
1173
  nua_destroy(ctx->a.nua), ctx->a.nua = NULL;

  su_root_destroy(ctx->root), ctx->root = NULL;

  su_home_deinit(tmphome);
1174

1175
  if (print_headings)
1176
    printf("TEST NUA-1.1: PASSED\n");
1177

Pekka Pessi's avatar
Pekka Pessi committed
1178
1179
1180
  END();
}

Pekka Pessi's avatar
Pekka Pessi committed
1181
1182
/* ======================================================================== */

1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
int test_stack_errors(struct context *ctx)
{
  BEGIN();

  struct endpoint *a = &ctx->a, *