~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjnath/src/pjnath-test/stun_sock_test.c

  • Committer: Package Import Robot
  • Author(s): Francois Marier, Francois Marier, Mark Purcell
  • Date: 2014-10-18 15:08:50 UTC
  • mfrom: (1.1.12)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20141018150850-2exfk34ckb15pcwi
Tags: 1.4.1-0.1
[ Francois Marier ]
* Non-maintainer upload
* New upstream release (closes: #759576, #741130)
  - debian/rules +PJPROJECT_VERSION := 2.2.1
  - add upstream patch to fix broken TLS support
  - add patch to fix pjproject regression

[ Mark Purcell ]
* Build-Depends:
  - sflphone-daemon + libavformat-dev, libavcodec-dev, libswscale-dev,
  libavdevice-dev, libavutil-dev
  - sflphone-gnome + libclutter-gtk-1.0-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: stun_sock_test.c 4360 2013-02-21 11:26:35Z bennylp $ */
2
 
/* 
3
 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
 
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
19
 
 */
20
 
#include "test.h"
21
 
 
22
 
#define THIS_FILE   "stun_sock_test.c"
23
 
 
24
 
enum {
25
 
    RESPOND_STUN    = 1,
26
 
    WITH_MAPPED     = 2,
27
 
    WITH_XOR_MAPPED = 4,
28
 
 
29
 
    ECHO            = 8
30
 
};
31
 
 
32
 
/*
33
 
 * Simple STUN server
34
 
 */
35
 
struct stun_srv
36
 
{
37
 
    pj_activesock_t     *asock;
38
 
    unsigned             flag;
39
 
    pj_sockaddr          addr;
40
 
    unsigned             rx_cnt;
41
 
    pj_ioqueue_op_key_t  send_key;
42
 
    pj_str_t             ip_to_send;
43
 
    pj_uint16_t          port_to_send;
44
 
};
45
 
 
46
 
static pj_bool_t srv_on_data_recvfrom(pj_activesock_t *asock,
47
 
                                      void *data,
48
 
                                      pj_size_t size,
49
 
                                      const pj_sockaddr_t *src_addr,
50
 
                                      int addr_len,
51
 
                                      pj_status_t status)
52
 
{
53
 
    struct stun_srv *srv;
54
 
    pj_ssize_t sent;
55
 
 
56
 
    srv = (struct stun_srv*) pj_activesock_get_user_data(asock);
57
 
 
58
 
    /* Ignore error */
59
 
    if (status != PJ_SUCCESS)
60
 
        return PJ_TRUE;
61
 
 
62
 
    ++srv->rx_cnt;
63
 
 
64
 
    /* Ignore if we're not responding */
65
 
    if (srv->flag & RESPOND_STUN) {
66
 
        pj_pool_t *pool;
67
 
        pj_stun_msg *req_msg, *res_msg;
68
 
 
69
 
        pool = pj_pool_create(mem, "stunsrv", 512, 512, NULL);
70
 
    
71
 
        /* Parse request */
72
 
        status = pj_stun_msg_decode(pool, (pj_uint8_t*)data, size, 
73
 
                                    PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET,
74
 
                                    &req_msg, NULL, NULL);
75
 
        if (status != PJ_SUCCESS) {
76
 
            app_perror("   pj_stun_msg_decode()", status);
77
 
            pj_pool_release(pool);
78
 
            return PJ_TRUE;
79
 
        }
80
 
 
81
 
        /* Create response */
82
 
        status = pj_stun_msg_create(pool, PJ_STUN_BINDING_RESPONSE, PJ_STUN_MAGIC,
83
 
                                    req_msg->hdr.tsx_id, &res_msg);
84
 
        if (status != PJ_SUCCESS) {
85
 
            app_perror("   pj_stun_msg_create()", status);
86
 
            pj_pool_release(pool);
87
 
            return PJ_TRUE;
88
 
        }
89
 
 
90
 
        /* Add MAPPED-ADDRESS or XOR-MAPPED-ADDRESS (or don't add) */
91
 
        if (srv->flag & WITH_MAPPED) {
92
 
            pj_sockaddr_in addr;
93
 
 
94
 
            pj_sockaddr_in_init(&addr, &srv->ip_to_send, srv->port_to_send);
95
 
            pj_stun_msg_add_sockaddr_attr(pool, res_msg, PJ_STUN_ATTR_MAPPED_ADDR,
96
 
                                          PJ_FALSE, &addr, sizeof(addr));
97
 
        } else if (srv->flag & WITH_XOR_MAPPED) {
98
 
            pj_sockaddr_in addr;
99
 
 
100
 
            pj_sockaddr_in_init(&addr, &srv->ip_to_send, srv->port_to_send);
101
 
            pj_stun_msg_add_sockaddr_attr(pool, res_msg, 
102
 
                                          PJ_STUN_ATTR_XOR_MAPPED_ADDR,
103
 
                                          PJ_TRUE, &addr, sizeof(addr));
104
 
        }
105
 
 
106
 
        /* Encode */
107
 
        status = pj_stun_msg_encode(res_msg, (pj_uint8_t*)data, 100, 0, 
108
 
                                    NULL, &size);
109
 
        if (status != PJ_SUCCESS) {
110
 
            app_perror("   pj_stun_msg_encode()", status);
111
 
            pj_pool_release(pool);
112
 
            return PJ_TRUE;
113
 
        }
114
 
 
115
 
        /* Send back */
116
 
        sent = size;
117
 
        pj_activesock_sendto(asock, &srv->send_key, data, &sent, 0, 
118
 
                             src_addr, addr_len);
119
 
 
120
 
        pj_pool_release(pool);
121
 
 
122
 
    } else if (srv->flag & ECHO) {
123
 
        /* Send back */
124
 
        sent = size;
125
 
        pj_activesock_sendto(asock, &srv->send_key, data, &sent, 0, 
126
 
                             src_addr, addr_len);
127
 
 
128
 
    }
129
 
 
130
 
    return PJ_TRUE;
131
 
}
132
 
 
133
 
static pj_status_t create_server(pj_pool_t *pool,
134
 
                                 pj_ioqueue_t *ioqueue,
135
 
                                 unsigned flag,
136
 
                                 struct stun_srv **p_srv)
137
 
{
138
 
    struct stun_srv *srv;
139
 
    pj_activesock_cb activesock_cb;
140
 
    pj_status_t status;
141
 
 
142
 
    srv = PJ_POOL_ZALLOC_T(pool, struct stun_srv);
143
 
    srv->flag = flag;
144
 
    srv->ip_to_send = pj_str("1.1.1.1");
145
 
    srv->port_to_send = 1000;
146
 
 
147
 
    status = pj_sockaddr_in_init(&srv->addr.ipv4, NULL, 0);
148
 
    if (status != PJ_SUCCESS)
149
 
        return status;
150
 
 
151
 
    pj_bzero(&activesock_cb, sizeof(activesock_cb));
152
 
    activesock_cb.on_data_recvfrom = &srv_on_data_recvfrom;
153
 
    status = pj_activesock_create_udp(pool, &srv->addr, NULL, ioqueue,
154
 
                                      &activesock_cb, srv, &srv->asock, 
155
 
                                      &srv->addr);
156
 
    if (status != PJ_SUCCESS)
157
 
        return status;
158
 
 
159
 
    pj_ioqueue_op_key_init(&srv->send_key, sizeof(srv->send_key));
160
 
 
161
 
    status = pj_activesock_start_recvfrom(srv->asock, pool, 512, 0);
162
 
    if (status != PJ_SUCCESS) {
163
 
        pj_activesock_close(srv->asock);
164
 
        return status;
165
 
    }
166
 
 
167
 
    *p_srv = srv;
168
 
    return PJ_SUCCESS;
169
 
}
170
 
 
171
 
static void destroy_server(struct stun_srv *srv)
172
 
{
173
 
    pj_activesock_close(srv->asock);
174
 
}
175
 
 
176
 
 
177
 
struct stun_client
178
 
{
179
 
    pj_pool_t           *pool;
180
 
    pj_stun_sock        *sock;
181
 
 
182
 
    pj_ioqueue_op_key_t  send_key;
183
 
    pj_bool_t            destroy_on_err;
184
 
 
185
 
    unsigned             on_status_cnt;
186
 
    pj_stun_sock_op      last_op;
187
 
    pj_status_t          last_status;
188
 
 
189
 
    unsigned             on_rx_data_cnt;
190
 
};
191
 
 
192
 
static pj_bool_t stun_sock_on_status(pj_stun_sock *stun_sock, 
193
 
                                     pj_stun_sock_op op,
194
 
                                     pj_status_t status)
195
 
{
196
 
    struct stun_client *client;
197
 
 
198
 
    client = (struct stun_client*) pj_stun_sock_get_user_data(stun_sock);
199
 
    client->on_status_cnt++;
200
 
    client->last_op = op;
201
 
    client->last_status = status;
202
 
 
203
 
    if (status != PJ_SUCCESS && client->destroy_on_err) {
204
 
        pj_stun_sock_destroy(client->sock);
205
 
        client->sock = NULL;
206
 
        return PJ_FALSE;
207
 
    }
208
 
 
209
 
    return PJ_TRUE;
210
 
}
211
 
 
212
 
static pj_bool_t stun_sock_on_rx_data(pj_stun_sock *stun_sock,
213
 
                                      void *pkt,
214
 
                                      unsigned pkt_len,
215
 
                                      const pj_sockaddr_t *src_addr,
216
 
                                      unsigned addr_len)
217
 
{
218
 
    struct stun_client *client;
219
 
 
220
 
    PJ_UNUSED_ARG(pkt);
221
 
    PJ_UNUSED_ARG(pkt_len);
222
 
    PJ_UNUSED_ARG(src_addr);
223
 
    PJ_UNUSED_ARG(addr_len);
224
 
 
225
 
    client = (struct stun_client*) pj_stun_sock_get_user_data(stun_sock);
226
 
    client->on_rx_data_cnt++;
227
 
 
228
 
    return PJ_TRUE;
229
 
}
230
 
 
231
 
static pj_status_t create_client(pj_stun_config *cfg,
232
 
                                 struct stun_client **p_client,
233
 
                                 pj_bool_t destroy_on_err)
234
 
{
235
 
    pj_pool_t *pool;
236
 
    struct stun_client *client;
237
 
    pj_stun_sock_cfg sock_cfg;
238
 
    pj_stun_sock_cb cb;
239
 
    pj_status_t status;
240
 
 
241
 
    pool = pj_pool_create(mem, "test", 512, 512, NULL);
242
 
    client = PJ_POOL_ZALLOC_T(pool, struct stun_client);
243
 
    client->pool = pool;
244
 
 
245
 
    pj_stun_sock_cfg_default(&sock_cfg);
246
 
 
247
 
    pj_bzero(&cb, sizeof(cb));
248
 
    cb.on_status = &stun_sock_on_status;
249
 
    cb.on_rx_data = &stun_sock_on_rx_data;
250
 
    status = pj_stun_sock_create(cfg, NULL, pj_AF_INET(), &cb,
251
 
                                 &sock_cfg, client, &client->sock);
252
 
    if (status != PJ_SUCCESS) {
253
 
        app_perror("   pj_stun_sock_create()", status);
254
 
        pj_pool_release(pool);
255
 
        return status;
256
 
    }
257
 
 
258
 
    pj_stun_sock_set_user_data(client->sock, client);
259
 
 
260
 
    pj_ioqueue_op_key_init(&client->send_key, sizeof(client->send_key));
261
 
 
262
 
    client->destroy_on_err = destroy_on_err;
263
 
 
264
 
    *p_client = client;
265
 
 
266
 
    return PJ_SUCCESS;
267
 
}
268
 
 
269
 
 
270
 
static void destroy_client(struct stun_client *client)
271
 
{
272
 
    if (client->sock) {
273
 
        pj_stun_sock_destroy(client->sock);
274
 
        client->sock = NULL;
275
 
    }
276
 
    pj_pool_release(client->pool);
277
 
}
278
 
 
279
 
static void handle_events(pj_stun_config *cfg, unsigned msec_delay)
280
 
{
281
 
    pj_time_val delay;
282
 
 
283
 
    pj_timer_heap_poll(cfg->timer_heap, NULL);
284
 
 
285
 
    delay.sec = 0;
286
 
    delay.msec = msec_delay;
287
 
    pj_time_val_normalize(&delay);
288
 
 
289
 
    pj_ioqueue_poll(cfg->ioqueue, &delay);
290
 
}
291
 
 
292
 
/*
293
 
 * Timeout test: scenario when no response is received from server
294
 
 */
295
 
static int timeout_test(pj_stun_config *cfg, pj_bool_t destroy_on_err)
296
 
{
297
 
    struct stun_srv *srv;
298
 
    struct stun_client *client;
299
 
    pj_str_t srv_addr;
300
 
    pj_time_val timeout, t;
301
 
    int i, ret = 0;
302
 
    pj_status_t status;
303
 
 
304
 
    PJ_LOG(3,(THIS_FILE, "  timeout test [%d]", destroy_on_err));
305
 
 
306
 
    status =  create_client(cfg, &client, destroy_on_err);
307
 
    if (status != PJ_SUCCESS)
308
 
        return -10;
309
 
 
310
 
    status = create_server(client->pool, cfg->ioqueue, 0, &srv);
311
 
    if (status != PJ_SUCCESS) {
312
 
        destroy_client(client);
313
 
        return -20;
314
 
    }
315
 
 
316
 
    srv_addr = pj_str("127.0.0.1");
317
 
    status = pj_stun_sock_start(client->sock, &srv_addr, 
318
 
                                pj_ntohs(srv->addr.ipv4.sin_port), NULL);
319
 
    if (status != PJ_SUCCESS) {
320
 
        destroy_server(srv);
321
 
        destroy_client(client);
322
 
        return -30;
323
 
    }
324
 
 
325
 
    /* Wait until on_status() callback is called with the failure */
326
 
    pj_gettimeofday(&timeout);
327
 
    timeout.sec += 60;
328
 
    do {
329
 
        handle_events(cfg, 100);
330
 
        pj_gettimeofday(&t);
331
 
    } while (client->on_status_cnt==0 && PJ_TIME_VAL_LT(t, timeout));
332
 
 
333
 
    /* Check that callback with correct operation is called */
334
 
    if (client->last_op != PJ_STUN_SOCK_BINDING_OP) {
335
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting Binding operation status"));
336
 
        ret = -40;
337
 
        goto on_return;
338
 
    }
339
 
    /* .. and with the correct status */
340
 
    if (client->last_status != PJNATH_ESTUNTIMEDOUT) {
341
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting PJNATH_ESTUNTIMEDOUT"));
342
 
        ret = -50;
343
 
        goto on_return;
344
 
    }
345
 
    /* Check that server received correct retransmissions */
346
 
    if (srv->rx_cnt != PJ_STUN_MAX_TRANSMIT_COUNT) {
347
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting %d retransmissions, got %d",
348
 
                   PJ_STUN_MAX_TRANSMIT_COUNT, srv->rx_cnt));
349
 
        ret = -60;
350
 
        goto on_return;
351
 
    }
352
 
    /* Check that client doesn't receive anything */
353
 
    if (client->on_rx_data_cnt != 0) {
354
 
        PJ_LOG(3,(THIS_FILE, "    error: client shouldn't have received anything"));
355
 
        ret = -70;
356
 
        goto on_return;
357
 
    }
358
 
 
359
 
on_return:
360
 
    destroy_server(srv);
361
 
    destroy_client(client);
362
 
    for (i=0; i<7; ++i)
363
 
        handle_events(cfg, 50);
364
 
    return ret;
365
 
}
366
 
 
367
 
 
368
 
/*
369
 
 * Invalid response scenario: when server returns no MAPPED-ADDRESS or
370
 
 * XOR-MAPPED-ADDRESS attribute.
371
 
 */
372
 
static int missing_attr_test(pj_stun_config *cfg, pj_bool_t destroy_on_err)
373
 
{
374
 
    struct stun_srv *srv;
375
 
    struct stun_client *client;
376
 
    pj_str_t srv_addr;
377
 
    pj_time_val timeout, t;
378
 
    int i, ret = 0;
379
 
    pj_status_t status;
380
 
 
381
 
    PJ_LOG(3,(THIS_FILE, "  missing attribute test [%d]", destroy_on_err));
382
 
 
383
 
    status =  create_client(cfg, &client, destroy_on_err);
384
 
    if (status != PJ_SUCCESS)
385
 
        return -110;
386
 
 
387
 
    status = create_server(client->pool, cfg->ioqueue, RESPOND_STUN, &srv);
388
 
    if (status != PJ_SUCCESS) {
389
 
        destroy_client(client);
390
 
        return -120;
391
 
    }
392
 
 
393
 
    srv_addr = pj_str("127.0.0.1");
394
 
    status = pj_stun_sock_start(client->sock, &srv_addr, 
395
 
                                pj_ntohs(srv->addr.ipv4.sin_port), NULL);
396
 
    if (status != PJ_SUCCESS) {
397
 
        destroy_server(srv);
398
 
        destroy_client(client);
399
 
        return -130;
400
 
    }
401
 
 
402
 
    /* Wait until on_status() callback is called with the failure */
403
 
    pj_gettimeofday(&timeout);
404
 
    timeout.sec += 60;
405
 
    do {
406
 
        handle_events(cfg, 100);
407
 
        pj_gettimeofday(&t);
408
 
    } while (client->on_status_cnt==0 && PJ_TIME_VAL_LT(t, timeout));
409
 
 
410
 
    /* Check that callback with correct operation is called */
411
 
    if (client->last_op != PJ_STUN_SOCK_BINDING_OP) {
412
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting Binding operation status"));
413
 
        ret = -140;
414
 
        goto on_return;
415
 
    }
416
 
    if (client->last_status != PJNATH_ESTUNNOMAPPEDADDR) {
417
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting PJNATH_ESTUNNOMAPPEDADDR"));
418
 
        ret = -150;
419
 
        goto on_return;
420
 
    }
421
 
    /* Check that client doesn't receive anything */
422
 
    if (client->on_rx_data_cnt != 0) {
423
 
        PJ_LOG(3,(THIS_FILE, "    error: client shouldn't have received anything"));
424
 
        ret = -170;
425
 
        goto on_return;
426
 
    }
427
 
 
428
 
on_return:
429
 
    destroy_server(srv);
430
 
    destroy_client(client);
431
 
    for (i=0; i<7; ++i)
432
 
        handle_events(cfg, 50);
433
 
    return ret;
434
 
}
435
 
 
436
 
/*
437
 
 * Keep-alive test.
438
 
 */
439
 
static int keep_alive_test(pj_stun_config *cfg)
440
 
{
441
 
    struct stun_srv *srv;
442
 
    struct stun_client *client;
443
 
    pj_sockaddr_in mapped_addr;
444
 
    pj_stun_sock_info info;
445
 
    pj_str_t srv_addr;
446
 
    pj_time_val timeout, t;
447
 
    int i, ret = 0;
448
 
    pj_status_t status;
449
 
 
450
 
    PJ_LOG(3,(THIS_FILE, "  normal operation"));
451
 
 
452
 
    status =  create_client(cfg, &client, PJ_TRUE);
453
 
    if (status != PJ_SUCCESS)
454
 
        return -310;
455
 
 
456
 
    status = create_server(client->pool, cfg->ioqueue, RESPOND_STUN|WITH_XOR_MAPPED, &srv);
457
 
    if (status != PJ_SUCCESS) {
458
 
        destroy_client(client);
459
 
        return -320;
460
 
    }
461
 
 
462
 
    /*
463
 
     * Part 1: initial Binding resolution.
464
 
     */
465
 
    PJ_LOG(3,(THIS_FILE, "    initial Binding request"));
466
 
    srv_addr = pj_str("127.0.0.1");
467
 
    status = pj_stun_sock_start(client->sock, &srv_addr, 
468
 
                                pj_ntohs(srv->addr.ipv4.sin_port), NULL);
469
 
    if (status != PJ_SUCCESS) {
470
 
        destroy_server(srv);
471
 
        destroy_client(client);
472
 
        return -330;
473
 
    }
474
 
 
475
 
    /* Wait until on_status() callback is called with success status */
476
 
    pj_gettimeofday(&timeout);
477
 
    timeout.sec += 60;
478
 
    do {
479
 
        handle_events(cfg, 100);
480
 
        pj_gettimeofday(&t);
481
 
    } while (client->on_status_cnt==0 && PJ_TIME_VAL_LT(t, timeout));
482
 
 
483
 
    /* Check that callback with correct operation is called */
484
 
    if (client->last_op != PJ_STUN_SOCK_BINDING_OP) {
485
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting Binding operation status"));
486
 
        ret = -340;
487
 
        goto on_return;
488
 
    }
489
 
    if (client->last_status != PJ_SUCCESS) {
490
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting PJ_SUCCESS status"));
491
 
        ret = -350;
492
 
        goto on_return;
493
 
    }
494
 
    /* Check that client doesn't receive anything */
495
 
    if (client->on_rx_data_cnt != 0) {
496
 
        PJ_LOG(3,(THIS_FILE, "    error: client shouldn't have received anything"));
497
 
        ret = -370;
498
 
        goto on_return;
499
 
    }
500
 
 
501
 
    /* Get info */
502
 
    pj_bzero(&info, sizeof(info));
503
 
    pj_stun_sock_get_info(client->sock, &info);
504
 
 
505
 
    /* Check that we have server address */
506
 
    if (!pj_sockaddr_has_addr(&info.srv_addr)) {
507
 
        PJ_LOG(3,(THIS_FILE, "    error: missing server address"));
508
 
        ret = -380;
509
 
        goto on_return;
510
 
    }
511
 
    /* .. and bound address port must not be zero */
512
 
    if (pj_sockaddr_get_port(&info.bound_addr)==0) {
513
 
        PJ_LOG(3,(THIS_FILE, "    error: bound address is zero"));
514
 
        ret = -381;
515
 
        goto on_return;
516
 
    }
517
 
    /* .. and mapped address */
518
 
    if (!pj_sockaddr_has_addr(&info.mapped_addr)) {
519
 
        PJ_LOG(3,(THIS_FILE, "    error: missing mapped address"));
520
 
        ret = -382;
521
 
        goto on_return;
522
 
    }
523
 
    /* verify the mapped address */
524
 
    pj_sockaddr_in_init(&mapped_addr, &srv->ip_to_send, srv->port_to_send);
525
 
    if (pj_sockaddr_cmp(&info.mapped_addr, &mapped_addr) != 0) {
526
 
        PJ_LOG(3,(THIS_FILE, "    error: mapped address mismatched"));
527
 
        ret = -383;
528
 
        goto on_return;
529
 
    }
530
 
 
531
 
    /* .. and at least one alias */
532
 
    if (info.alias_cnt == 0) {
533
 
        PJ_LOG(3,(THIS_FILE, "    error: must have at least one alias"));
534
 
        ret = -384;
535
 
        goto on_return;
536
 
    }
537
 
    if (!pj_sockaddr_has_addr(&info.aliases[0])) {
538
 
        PJ_LOG(3,(THIS_FILE, "    error: missing alias"));
539
 
        ret = -386;
540
 
        goto on_return;
541
 
    }
542
 
 
543
 
 
544
 
    /*
545
 
     * Part 2: sending and receiving data
546
 
     */
547
 
    PJ_LOG(3,(THIS_FILE, "    sending/receiving data"));
548
 
 
549
 
    /* Change server operation mode to echo back data */
550
 
    srv->flag = ECHO;
551
 
 
552
 
    /* Reset server */
553
 
    srv->rx_cnt = 0;
554
 
 
555
 
    /* Client sending data to echo server */
556
 
    {
557
 
        char txt[100];
558
 
        PJ_LOG(3,(THIS_FILE, "     sending to %s", pj_sockaddr_print(&info.srv_addr, txt, sizeof(txt), 3)));
559
 
    }
560
 
    status = pj_stun_sock_sendto(client->sock, NULL, &ret, sizeof(ret),
561
 
                                 0, &info.srv_addr, 
562
 
                                 pj_sockaddr_get_len(&info.srv_addr));
563
 
    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
564
 
        app_perror("    error: server sending data", status);
565
 
        ret = -390;
566
 
        goto on_return;
567
 
    }
568
 
 
569
 
    /* Wait for a short period until client receives data. We can't wait for
570
 
     * too long otherwise the keep-alive will kick in.
571
 
     */
572
 
    pj_gettimeofday(&timeout);
573
 
    timeout.sec += 1;
574
 
    do {
575
 
        handle_events(cfg, 100);
576
 
        pj_gettimeofday(&t);
577
 
    } while (client->on_rx_data_cnt==0 && PJ_TIME_VAL_LT(t, timeout));
578
 
 
579
 
    /* Check that data is received in server */
580
 
    if (srv->rx_cnt == 0) {
581
 
        PJ_LOG(3,(THIS_FILE, "    error: server didn't receive data"));
582
 
        ret = -395;
583
 
        goto on_return;
584
 
    }
585
 
 
586
 
    /* Check that status is still OK */
587
 
    if (client->last_status != PJ_SUCCESS) {
588
 
        app_perror("    error: client has failed", client->last_status);
589
 
        ret = -400;
590
 
        goto on_return;
591
 
    }
592
 
    /* Check that data has been received */
593
 
    if (client->on_rx_data_cnt == 0) {
594
 
        PJ_LOG(3,(THIS_FILE, "    error: client doesn't receive data"));
595
 
        ret = -410;
596
 
        goto on_return;
597
 
    }
598
 
 
599
 
    /*
600
 
     * Part 3: Successful keep-alive,
601
 
     */
602
 
    PJ_LOG(3,(THIS_FILE, "    successful keep-alive scenario"));
603
 
 
604
 
    /* Change server operation mode to normal mode */
605
 
    srv->flag = RESPOND_STUN | WITH_XOR_MAPPED;
606
 
 
607
 
    /* Reset server */
608
 
    srv->rx_cnt = 0;
609
 
 
610
 
    /* Reset client */
611
 
    client->on_status_cnt = 0;
612
 
    client->last_status = PJ_SUCCESS;
613
 
    client->on_rx_data_cnt = 0;
614
 
 
615
 
    /* Wait for keep-alive duration to see if client actually sends the
616
 
     * keep-alive.
617
 
     */
618
 
    pj_gettimeofday(&timeout);
619
 
    timeout.sec += (PJ_STUN_KEEP_ALIVE_SEC + 1);
620
 
    do {
621
 
        handle_events(cfg, 100);
622
 
        pj_gettimeofday(&t);
623
 
    } while (PJ_TIME_VAL_LT(t, timeout));
624
 
 
625
 
    /* Check that server receives some packets */
626
 
    if (srv->rx_cnt == 0) {
627
 
        PJ_LOG(3, (THIS_FILE, "    error: no keep-alive was received"));
628
 
        ret = -420;
629
 
        goto on_return;
630
 
    }
631
 
    /* Check that client status is still okay and on_status() callback is NOT
632
 
     * called
633
 
     */
634
 
    /* No longer valid due to this ticket:
635
 
     *  http://trac.pjsip.org/repos/ticket/742
636
 
 
637
 
    if (client->on_status_cnt != 0) {
638
 
        PJ_LOG(3, (THIS_FILE, "    error: on_status() must not be called on successful"
639
 
                              "keep-alive when mapped-address does not change"));
640
 
        ret = -430;
641
 
        goto on_return;
642
 
    }
643
 
    */
644
 
    /* Check that client doesn't receive anything */
645
 
    if (client->on_rx_data_cnt != 0) {
646
 
        PJ_LOG(3,(THIS_FILE, "    error: client shouldn't have received anything"));
647
 
        ret = -440;
648
 
        goto on_return;
649
 
    }
650
 
 
651
 
 
652
 
    /*
653
 
     * Part 4: Successful keep-alive with IP address change
654
 
     */
655
 
    PJ_LOG(3,(THIS_FILE, "    mapped IP address change"));
656
 
 
657
 
    /* Change server operation mode to normal mode */
658
 
    srv->flag = RESPOND_STUN | WITH_XOR_MAPPED;
659
 
 
660
 
    /* Change mapped address in the response */
661
 
    srv->ip_to_send = pj_str("2.2.2.2");
662
 
    srv->port_to_send++;
663
 
 
664
 
    /* Reset server */
665
 
    srv->rx_cnt = 0;
666
 
 
667
 
    /* Reset client */
668
 
    client->on_status_cnt = 0;
669
 
    client->last_status = PJ_SUCCESS;
670
 
    client->on_rx_data_cnt = 0;
671
 
 
672
 
    /* Wait for keep-alive duration to see if client actually sends the
673
 
     * keep-alive.
674
 
     */
675
 
    pj_gettimeofday(&timeout);
676
 
    timeout.sec += (PJ_STUN_KEEP_ALIVE_SEC + 1);
677
 
    do {
678
 
        handle_events(cfg, 100);
679
 
        pj_gettimeofday(&t);
680
 
    } while (PJ_TIME_VAL_LT(t, timeout));
681
 
 
682
 
    /* Check that server receives some packets */
683
 
    if (srv->rx_cnt == 0) {
684
 
        PJ_LOG(3, (THIS_FILE, "    error: no keep-alive was received"));
685
 
        ret = -450;
686
 
        goto on_return;
687
 
    }
688
 
    /* Check that on_status() callback is called (because mapped address
689
 
     * has changed)
690
 
     */
691
 
    if (client->on_status_cnt != 1) {
692
 
        PJ_LOG(3, (THIS_FILE, "    error: on_status() was not called"));
693
 
        ret = -460;
694
 
        goto on_return;
695
 
    }
696
 
    /* Check that callback was called with correct operation */
697
 
    if (client->last_op != PJ_STUN_SOCK_MAPPED_ADDR_CHANGE) {
698
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting keep-alive operation status"));
699
 
        ret = -470;
700
 
        goto on_return;
701
 
    }
702
 
    /* Check that last status is still success */
703
 
    if (client->last_status != PJ_SUCCESS) {
704
 
        PJ_LOG(3, (THIS_FILE, "    error: expecting successful status"));
705
 
        ret = -480;
706
 
        goto on_return;
707
 
    }
708
 
    /* Check that client doesn't receive anything */
709
 
    if (client->on_rx_data_cnt != 0) {
710
 
        PJ_LOG(3,(THIS_FILE, "    error: client shouldn't have received anything"));
711
 
        ret = -490;
712
 
        goto on_return;
713
 
    }
714
 
 
715
 
    /* Get info */
716
 
    pj_bzero(&info, sizeof(info));
717
 
    pj_stun_sock_get_info(client->sock, &info);
718
 
 
719
 
    /* Check that we have server address */
720
 
    if (!pj_sockaddr_has_addr(&info.srv_addr)) {
721
 
        PJ_LOG(3,(THIS_FILE, "    error: missing server address"));
722
 
        ret = -500;
723
 
        goto on_return;
724
 
    }
725
 
    /* .. and mapped address */
726
 
    if (!pj_sockaddr_has_addr(&info.mapped_addr)) {
727
 
        PJ_LOG(3,(THIS_FILE, "    error: missing mapped address"));
728
 
        ret = -510;
729
 
        goto on_return;
730
 
    }
731
 
    /* verify the mapped address */
732
 
    pj_sockaddr_in_init(&mapped_addr, &srv->ip_to_send, srv->port_to_send);
733
 
    if (pj_sockaddr_cmp(&info.mapped_addr, &mapped_addr) != 0) {
734
 
        PJ_LOG(3,(THIS_FILE, "    error: mapped address mismatched"));
735
 
        ret = -520;
736
 
        goto on_return;
737
 
    }
738
 
 
739
 
    /* .. and at least one alias */
740
 
    if (info.alias_cnt == 0) {
741
 
        PJ_LOG(3,(THIS_FILE, "    error: must have at least one alias"));
742
 
        ret = -530;
743
 
        goto on_return;
744
 
    }
745
 
    if (!pj_sockaddr_has_addr(&info.aliases[0])) {
746
 
        PJ_LOG(3,(THIS_FILE, "    error: missing alias"));
747
 
        ret = -540;
748
 
        goto on_return;
749
 
    }
750
 
 
751
 
 
752
 
    /*
753
 
     * Part 5: Failed keep-alive
754
 
     */
755
 
    PJ_LOG(3,(THIS_FILE, "    failed keep-alive scenario"));
756
 
    
757
 
    /* Change server operation mode to respond without attribute */
758
 
    srv->flag = RESPOND_STUN;
759
 
 
760
 
    /* Reset server */
761
 
    srv->rx_cnt = 0;
762
 
 
763
 
    /* Reset client */
764
 
    client->on_status_cnt = 0;
765
 
    client->last_status = PJ_SUCCESS;
766
 
    client->on_rx_data_cnt = 0;
767
 
 
768
 
    /* Wait until on_status() is called with failure. */
769
 
    pj_gettimeofday(&timeout);
770
 
    timeout.sec += (PJ_STUN_KEEP_ALIVE_SEC + PJ_STUN_TIMEOUT_VALUE + 5);
771
 
    do {
772
 
        handle_events(cfg, 100);
773
 
        pj_gettimeofday(&t);
774
 
    } while (client->on_status_cnt==0 && PJ_TIME_VAL_LT(t, timeout));
775
 
 
776
 
    /* Check that callback with correct operation is called */
777
 
    if (client->last_op != PJ_STUN_SOCK_KEEP_ALIVE_OP) {
778
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting keep-alive operation status"));
779
 
        ret = -600;
780
 
        goto on_return;
781
 
    }
782
 
    if (client->last_status == PJ_SUCCESS) {
783
 
        PJ_LOG(3,(THIS_FILE, "    error: expecting failed keep-alive"));
784
 
        ret = -610;
785
 
        goto on_return;
786
 
    }
787
 
    /* Check that client doesn't receive anything */
788
 
    if (client->on_rx_data_cnt != 0) {
789
 
        PJ_LOG(3,(THIS_FILE, "    error: client shouldn't have received anything"));
790
 
        ret = -620;
791
 
        goto on_return;
792
 
    }
793
 
 
794
 
 
795
 
on_return:
796
 
    destroy_server(srv);
797
 
    destroy_client(client);
798
 
    for (i=0; i<7; ++i)
799
 
        handle_events(cfg, 50);
800
 
    return ret;
801
 
}
802
 
 
803
 
 
804
 
#define DO_TEST(expr)       \
805
 
            capture_pjlib_state(&stun_cfg, &pjlib_state); \
806
 
            ret = expr; \
807
 
            if (ret != 0) goto on_return; \
808
 
            ret = check_pjlib_state(&stun_cfg, &pjlib_state); \
809
 
            if (ret != 0) goto on_return;
810
 
 
811
 
 
812
 
int stun_sock_test(void)
813
 
{
814
 
    struct pjlib_state pjlib_state;
815
 
    pj_stun_config stun_cfg;
816
 
    pj_ioqueue_t *ioqueue = NULL;
817
 
    pj_timer_heap_t *timer_heap = NULL;
818
 
    pj_pool_t *pool = NULL;
819
 
    pj_status_t status;
820
 
    int ret = 0;
821
 
 
822
 
    pool = pj_pool_create(mem, NULL, 512, 512, NULL);
823
 
 
824
 
    status = pj_ioqueue_create(pool, 12, &ioqueue);
825
 
    if (status != PJ_SUCCESS) {
826
 
        app_perror("   pj_ioqueue_create()", status);
827
 
        ret = -4;
828
 
        goto on_return;
829
 
    }
830
 
 
831
 
    status = pj_timer_heap_create(pool, 100, &timer_heap);
832
 
    if (status != PJ_SUCCESS) {
833
 
        app_perror("   pj_timer_heap_create()", status);
834
 
        ret = -8;
835
 
        goto on_return;
836
 
    }
837
 
    
838
 
    pj_stun_config_init(&stun_cfg, mem, 0, ioqueue, timer_heap);
839
 
 
840
 
    DO_TEST(timeout_test(&stun_cfg, PJ_FALSE));
841
 
    DO_TEST(timeout_test(&stun_cfg, PJ_TRUE));
842
 
 
843
 
    DO_TEST(missing_attr_test(&stun_cfg, PJ_FALSE));
844
 
    DO_TEST(missing_attr_test(&stun_cfg, PJ_TRUE));
845
 
 
846
 
    DO_TEST(keep_alive_test(&stun_cfg));
847
 
 
848
 
on_return:
849
 
    if (timer_heap) pj_timer_heap_destroy(timer_heap);
850
 
    if (ioqueue) pj_ioqueue_destroy(ioqueue);
851
 
    if (pool) pj_pool_release(pool);
852
 
    return ret;
853
 
}
854
 
 
855