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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjlib-util/src/pjlib-util-test/http_client.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: http_client.c 3553 2011-05-05 06:14:19Z nanang $ */
2
 
/*
3
 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
 */
19
 
 
20
 
#include "test.h"
21
 
 
22
 
#if INCLUDE_HTTP_CLIENT_TEST
23
 
 
24
 
#define THIS_FILE           "test_http"
25
 
//#define VERBOSE
26
 
#define STR_PREC(s) (int)s.slen, s.ptr
27
 
#define USE_LOCAL_SERVER
28
 
 
29
 
#include <pjlib.h>
30
 
#include <pjlib-util.h>
31
 
 
32
 
#define ACTION_REPLY    0
33
 
#define ACTION_IGNORE   -1
34
 
 
35
 
static struct server_t
36
 
{
37
 
    pj_sock_t        sock;
38
 
    pj_uint16_t      port;
39
 
    pj_thread_t     *thread;
40
 
 
41
 
    /* Action:
42
 
     *  0:    reply with the response in resp.
43
 
     * -1:    ignore query (to simulate timeout).
44
 
     * other: reply with that error
45
 
     */
46
 
    int             action;
47
 
    pj_bool_t       send_content_length;
48
 
    unsigned        data_size;
49
 
    unsigned        buf_size;
50
 
} g_server;
51
 
 
52
 
static pj_bool_t thread_quit;
53
 
static pj_timer_heap_t *timer_heap;
54
 
static pj_ioqueue_t *ioqueue;
55
 
static pj_pool_t *pool;
56
 
static pj_http_req *http_req;
57
 
static pj_bool_t test_cancel = PJ_FALSE;
58
 
static pj_size_t total_size;
59
 
static pj_size_t send_size = 0;
60
 
static pj_status_t sstatus;
61
 
static pj_sockaddr_in addr;
62
 
static int counter = 0;
63
 
 
64
 
static int server_thread(void *p)
65
 
{
66
 
    struct server_t *srv = (struct server_t*)p;
67
 
    char *pkt = (char*)pj_pool_alloc(pool, srv->buf_size);
68
 
    pj_sock_t newsock = PJ_INVALID_SOCKET;
69
 
 
70
 
    while (!thread_quit) {
71
 
        pj_ssize_t pkt_len;
72
 
        int rc;
73
 
        pj_fd_set_t rset;
74
 
        pj_time_val timeout = {0, 500};
75
 
 
76
 
        while (!thread_quit) {
77
 
            PJ_FD_ZERO(&rset);
78
 
            PJ_FD_SET(srv->sock, &rset);
79
 
            rc = pj_sock_select(srv->sock+1, &rset, NULL, NULL, &timeout);
80
 
            if (rc != 1) {
81
 
                continue;
82
 
            }
83
 
 
84
 
            rc = pj_sock_accept(srv->sock, &newsock, NULL, NULL);
85
 
            if (rc == PJ_SUCCESS) {
86
 
                break;
87
 
            }
88
 
        }
89
 
 
90
 
        if (thread_quit)
91
 
            break;
92
 
 
93
 
        while (!thread_quit) {
94
 
            PJ_FD_ZERO(&rset);
95
 
            PJ_FD_SET(newsock, &rset);
96
 
            rc = pj_sock_select(newsock+1, &rset, NULL, NULL, &timeout);
97
 
            if (rc != 1) {
98
 
                PJ_LOG(3,("http test", "client timeout"));
99
 
                continue;
100
 
            }
101
 
 
102
 
            pkt_len = srv->buf_size;
103
 
            rc = pj_sock_recv(newsock, pkt, &pkt_len, 0);
104
 
            if (rc == PJ_SUCCESS) {
105
 
                break;
106
 
            }
107
 
        }
108
 
 
109
 
        if (thread_quit)
110
 
            break;
111
 
 
112
 
        /* Simulate network RTT */
113
 
        pj_thread_sleep(50);
114
 
 
115
 
        if (srv->action == ACTION_IGNORE) {
116
 
            continue;
117
 
        } else if (srv->action == ACTION_REPLY) {
118
 
            unsigned send_size = 0, ctr = 0;
119
 
            pj_ansi_sprintf(pkt, "HTTP/1.0 200 OK\r\n");
120
 
            if (srv->send_content_length) {
121
 
                pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt),
122
 
                                "Content-Length: %d\r\n",
123
 
                                srv->data_size);
124
 
            }
125
 
            pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "\r\n");
126
 
            pkt_len = pj_ansi_strlen(pkt);
127
 
            rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
128
 
            if (rc != PJ_SUCCESS) {
129
 
                pj_sock_close(newsock);
130
 
                continue;
131
 
            }
132
 
            while (send_size < srv->data_size) {
133
 
                pkt_len = srv->data_size - send_size;
134
 
                if (pkt_len > (signed)srv->buf_size)
135
 
                    pkt_len = srv->buf_size;
136
 
                send_size += pkt_len;
137
 
                pj_create_random_string(pkt, pkt_len);
138
 
                pj_ansi_sprintf(pkt, "\nPacket: %d", ++ctr);
139
 
                pkt[pj_ansi_strlen(pkt)] = '\n';
140
 
                rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
141
 
                if (rc != PJ_SUCCESS)
142
 
                    break;
143
 
            }
144
 
            pj_sock_close(newsock);
145
 
        }
146
 
    }
147
 
 
148
 
    return 0;
149
 
}
150
 
 
151
 
static void on_data_read(pj_http_req *hreq, void *data, pj_size_t size)
152
 
{
153
 
    PJ_UNUSED_ARG(hreq);
154
 
    PJ_UNUSED_ARG(data);
155
 
 
156
 
    PJ_LOG(5, (THIS_FILE, "\nData received: %d bytes", size));
157
 
    if (size > 0) {
158
 
#ifdef VERBOSE
159
 
        printf("%.*s\n", (int)size, (char *)data);
160
 
#endif
161
 
    }
162
 
}
163
 
 
164
 
static void on_send_data(pj_http_req *hreq,
165
 
                         void **data, pj_size_t *size)
166
 
{
167
 
    char *sdata;
168
 
    pj_size_t sendsz = 8397;
169
 
 
170
 
    PJ_UNUSED_ARG(hreq);
171
 
 
172
 
    if (send_size + sendsz > total_size) {
173
 
        sendsz = total_size - send_size;
174
 
    }
175
 
    send_size += sendsz;
176
 
 
177
 
    sdata = (char*)pj_pool_alloc(pool, sendsz);
178
 
    pj_create_random_string(sdata, sendsz);
179
 
    pj_ansi_sprintf(sdata, "\nSegment #%d\n", ++counter);
180
 
    *data = sdata;
181
 
    *size = sendsz;
182
 
 
183
 
    PJ_LOG(5, (THIS_FILE, "\nSending data progress: %d out of %d bytes",
184
 
           send_size, total_size));
185
 
}
186
 
 
187
 
 
188
 
static void on_complete(pj_http_req *hreq, pj_status_t status,
189
 
                        const pj_http_resp *resp)
190
 
{
191
 
    PJ_UNUSED_ARG(hreq);
192
 
 
193
 
    if (status == PJ_ECANCELLED) {
194
 
        PJ_LOG(5, (THIS_FILE, "Request cancelled"));
195
 
        return;
196
 
    } else if (status == PJ_ETIMEDOUT) {
197
 
        PJ_LOG(5, (THIS_FILE, "Request timed out!"));
198
 
        return;
199
 
    } else if (status != PJ_SUCCESS) {
200
 
        PJ_LOG(3, (THIS_FILE, "Error %d", status));
201
 
        return;
202
 
    }
203
 
    PJ_LOG(5, (THIS_FILE, "\nData completed: %d bytes", resp->size));
204
 
    if (resp->size > 0 && resp->data) {
205
 
#ifdef VERBOSE
206
 
        printf("%.*s\n", (int)resp->size, (char *)resp->data);
207
 
#endif
208
 
    }
209
 
}
210
 
 
211
 
static void on_response(pj_http_req *hreq, const pj_http_resp *resp)
212
 
{
213
 
    pj_size_t i;
214
 
 
215
 
    PJ_UNUSED_ARG(hreq);
216
 
    PJ_UNUSED_ARG(resp);
217
 
    PJ_UNUSED_ARG(i);
218
 
 
219
 
#ifdef VERBOSE
220
 
    printf("%.*s, %d, %.*s\n", STR_PREC(resp->version),
221
 
           resp->status_code, STR_PREC(resp->reason));
222
 
    for (i = 0; i < resp->headers.count; i++) {
223
 
        printf("%.*s : %.*s\n",
224
 
               STR_PREC(resp->headers.header[i].name),
225
 
               STR_PREC(resp->headers.header[i].value));
226
 
    }
227
 
#endif
228
 
 
229
 
    if (test_cancel) {
230
 
        /* Need to delay closing the client socket here, otherwise the
231
 
         * server will get SIGPIPE when sending response.
232
 
         */
233
 
        pj_thread_sleep(100);
234
 
        pj_http_req_cancel(hreq, PJ_TRUE);
235
 
        test_cancel = PJ_FALSE;
236
 
    }
237
 
}
238
 
 
239
 
 
240
 
pj_status_t parse_url(const char *url, pj_http_url *hurl)
241
 
{
242
 
    pj_str_t surl;
243
 
    pj_status_t status;
244
 
 
245
 
    pj_cstr(&surl, url);
246
 
    status = pj_http_req_parse_url(&surl, hurl);
247
 
#ifdef VERBOSE
248
 
    if (!status) {
249
 
        printf("URL: %s\nProtocol: %.*s\nHost: %.*s\nPort: %d\nPath: %.*s\n\n",
250
 
               url, STR_PREC(hurl->protocol), STR_PREC(hurl->host),
251
 
               hurl->port, STR_PREC(hurl->path));
252
 
    } else {
253
 
    }
254
 
#endif
255
 
    return status;
256
 
}
257
 
 
258
 
static int parse_url_test()
259
 
{
260
 
    struct test_data
261
 
    {
262
 
        char *url;
263
 
        pj_status_t result;
264
 
        const char *username;
265
 
        const char *passwd;
266
 
        const char *host;
267
 
        int port;
268
 
        const char *path;
269
 
    } test_data[] =
270
 
    {
271
 
        /* Simple URL without '/' in the end */
272
 
        {"http://www.pjsip.org", PJ_SUCCESS, "", "", "www.pjsip.org", 80, "/"},
273
 
 
274
 
        /* Simple URL with port number but without '/' in the end */
275
 
        {"http://pjsip.org:8080", PJ_SUCCESS, "", "", "pjsip.org", 8080, "/"},
276
 
 
277
 
        /* URL with path */
278
 
        {"http://127.0.0.1:280/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6",
279
 
                PJ_SUCCESS, "", "", "127.0.0.1", 280,
280
 
                "/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6"},
281
 
 
282
 
        /* URL with port and path */
283
 
        {"http://pjsip.org:81/about-us/", PJ_SUCCESS, "", "", "pjsip.org", 81, "/about-us/"},
284
 
 
285
 
        /* unsupported protocol */
286
 
        {"ftp://www.pjsip.org", PJ_ENOTSUP, "", "", "", 80, ""},
287
 
 
288
 
        /* invalid format */
289
 
        {"http:/pjsip.org/about-us/", PJLIB_UTIL_EHTTPINURL, "", "", "", 80, ""},
290
 
 
291
 
        /* invalid port number */
292
 
        {"http://pjsip.org:xyz/", PJLIB_UTIL_EHTTPINPORT, "", "", "", 80, ""},
293
 
 
294
 
        /* with username and password */
295
 
        {"http://user:pass@pjsip.org", PJ_SUCCESS, "user", "pass", "pjsip.org", 80, "/"},
296
 
 
297
 
        /* password only*/
298
 
        {"http://:pass@pjsip.org", PJ_SUCCESS, "", "pass", "pjsip.org", 80, "/"},
299
 
 
300
 
        /* user only*/
301
 
        {"http://user:@pjsip.org", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/"},
302
 
 
303
 
        /* empty username and passwd*/
304
 
        {"http://:@pjsip.org", PJ_SUCCESS, "", "", "pjsip.org", 80, "/"},
305
 
 
306
 
        /* '@' character in username and path */
307
 
        {"http://user@pjsip.org/@", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/@"},
308
 
 
309
 
        /* '@' character in path */
310
 
        {"http://pjsip.org/@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/@"},
311
 
 
312
 
        /* '@' character in path */
313
 
        {"http://pjsip.org/one@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/one@"},
314
 
 
315
 
        /* Invalid URL */
316
 
        {"http://:", PJ_EINVAL, "", "", "", 0, ""},
317
 
 
318
 
        /* Invalid URL */
319
 
        {"http://@", PJ_EINVAL, "", "", "", 0, ""},
320
 
 
321
 
        /* Invalid URL */
322
 
        {"http", PJ_EINVAL, "", "", "", 0, ""},
323
 
 
324
 
        /* Invalid URL */
325
 
        {"http:/", PJ_EINVAL, "", "", "", 0, ""},
326
 
 
327
 
        /* Invalid URL */
328
 
        {"http://", PJ_EINVAL, "", "", "", 0, ""},
329
 
 
330
 
        /* Invalid URL */
331
 
        {"http:///", PJ_EINVAL, "", "", "", 0, ""},
332
 
 
333
 
        /* Invalid URL */
334
 
        {"http://@/", PJ_EINVAL, "", "", "", 0, ""},
335
 
 
336
 
        /* Invalid URL */
337
 
        {"http:///@", PJ_EINVAL, "", "", "", 0, ""},
338
 
 
339
 
        /* Invalid URL */
340
 
        {"http://:::", PJ_EINVAL, "", "", "", 0, ""},
341
 
    };
342
 
    unsigned i;
343
 
 
344
 
    for (i=0; i<PJ_ARRAY_SIZE(test_data); ++i) {
345
 
        struct test_data *ptd;
346
 
        pj_http_url hurl;
347
 
        pj_status_t status;
348
 
 
349
 
        ptd = &test_data[i];
350
 
 
351
 
        PJ_LOG(3, (THIS_FILE, ".. %s", ptd->url));
352
 
        status = parse_url(ptd->url, &hurl);
353
 
 
354
 
        if (status != ptd->result) {
355
 
            PJ_LOG(3,(THIS_FILE, "%d", status));
356
 
            return -11;
357
 
        }
358
 
        if (status != PJ_SUCCESS)
359
 
            continue;
360
 
        if (pj_strcmp2(&hurl.username, ptd->username))
361
 
            return -12;
362
 
        if (pj_strcmp2(&hurl.passwd, ptd->passwd))
363
 
            return -13;
364
 
        if (pj_strcmp2(&hurl.host, ptd->host))
365
 
            return -14;
366
 
        if (hurl.port != ptd->port)
367
 
            return -15;
368
 
        if (pj_strcmp2(&hurl.path, ptd->path))
369
 
            return -16;
370
 
    }
371
 
 
372
 
    return 0;
373
 
}
374
 
 
375
 
/*
376
 
 * GET request scenario 1: using on_response() and on_data_read()
377
 
 * Server replies with content-length. Application cancels the
378
 
 * request upon receiving the response, then start it again.
379
 
 */
380
 
int http_client_test1()
381
 
{
382
 
    pj_str_t url;
383
 
    pj_http_req_callback hcb;
384
 
    pj_http_req_param param;
385
 
    char urlbuf[80];
386
 
 
387
 
    pj_bzero(&hcb, sizeof(hcb));
388
 
    hcb.on_complete = &on_complete;
389
 
    hcb.on_data_read = &on_data_read;
390
 
    hcb.on_response = &on_response;
391
 
    pj_http_req_param_default(&param);
392
 
 
393
 
    /* Create pool, timer, and ioqueue */
394
 
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
395
 
    if (pj_timer_heap_create(pool, 16, &timer_heap))
396
 
        return -31;
397
 
    if (pj_ioqueue_create(pool, 16, &ioqueue))
398
 
        return -32;
399
 
 
400
 
#ifdef USE_LOCAL_SERVER
401
 
 
402
 
    thread_quit = PJ_FALSE;
403
 
    g_server.action = ACTION_REPLY;
404
 
    g_server.send_content_length = PJ_TRUE;
405
 
    g_server.data_size = 2970;
406
 
    g_server.buf_size = 1024;
407
 
 
408
 
    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
409
 
                             &g_server.sock);
410
 
    if (sstatus != PJ_SUCCESS)
411
 
        return -41;
412
 
 
413
 
    pj_sockaddr_in_init(&addr, NULL, 0);
414
 
 
415
 
    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
416
 
    if (sstatus != PJ_SUCCESS)
417
 
        return -43;
418
 
 
419
 
    {
420
 
        pj_sockaddr_in addr;
421
 
        int addr_len = sizeof(addr);
422
 
        sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
423
 
        if (sstatus != PJ_SUCCESS)
424
 
            return -44;
425
 
        g_server.port = pj_sockaddr_in_get_port(&addr);
426
 
        pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
427
 
                         "http://127.0.0.1:%d/about-us/",
428
 
                         g_server.port);
429
 
        url = pj_str(urlbuf);
430
 
    }
431
 
 
432
 
    sstatus = pj_sock_listen(g_server.sock, 8);
433
 
    if (sstatus != PJ_SUCCESS)
434
 
        return -45;
435
 
 
436
 
    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
437
 
                               0, 0, &g_server.thread);
438
 
    if (sstatus != PJ_SUCCESS)
439
 
        return -47;
440
 
 
441
 
#else
442
 
    pj_cstr(&url, "http://www.teluu.com/about-us/");
443
 
#endif
444
 
 
445
 
    if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
446
 
                           &param, &hcb, &http_req))
447
 
        return -33;
448
 
 
449
 
    test_cancel = PJ_TRUE;
450
 
    if (pj_http_req_start(http_req))
451
 
        return -35;
452
 
 
453
 
    while (pj_http_req_is_running(http_req)) {
454
 
        pj_time_val delay = {0, 50};
455
 
        pj_ioqueue_poll(ioqueue, &delay);
456
 
        pj_timer_heap_poll(timer_heap, NULL);
457
 
    }
458
 
 
459
 
    if (pj_http_req_start(http_req))
460
 
        return -37;
461
 
 
462
 
    while (pj_http_req_is_running(http_req)) {
463
 
        pj_time_val delay = {0, 50};
464
 
        pj_ioqueue_poll(ioqueue, &delay);
465
 
        pj_timer_heap_poll(timer_heap, NULL);
466
 
    }
467
 
 
468
 
#ifdef USE_LOCAL_SERVER
469
 
    thread_quit = PJ_TRUE;
470
 
    pj_thread_join(g_server.thread);
471
 
    pj_sock_close(g_server.sock);
472
 
#endif
473
 
 
474
 
    pj_http_req_destroy(http_req);
475
 
    pj_ioqueue_destroy(ioqueue);
476
 
    pj_timer_heap_destroy(timer_heap);
477
 
    pj_pool_release(pool);
478
 
 
479
 
    return PJ_SUCCESS;
480
 
}
481
 
 
482
 
/*
483
 
 * GET request scenario 2: using on_complete() to get the
484
 
 * complete data. Server does not reply with content-length.
485
 
 * Request timed out, application sets a longer timeout, then
486
 
 * then restart the request.
487
 
 */
488
 
int http_client_test2()
489
 
{
490
 
    pj_str_t url;
491
 
    pj_http_req_callback hcb;
492
 
    pj_http_req_param param;
493
 
    pj_time_val timeout;
494
 
    char urlbuf[80];
495
 
 
496
 
    pj_bzero(&hcb, sizeof(hcb));
497
 
    hcb.on_complete = &on_complete;
498
 
    hcb.on_response = &on_response;
499
 
    pj_http_req_param_default(&param);
500
 
 
501
 
    /* Create pool, timer, and ioqueue */
502
 
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
503
 
    if (pj_timer_heap_create(pool, 16, &timer_heap))
504
 
        return -41;
505
 
    if (pj_ioqueue_create(pool, 16, &ioqueue))
506
 
        return -42;
507
 
 
508
 
#ifdef USE_LOCAL_SERVER
509
 
 
510
 
    pj_cstr(&url, "http://127.0.0.1:380");
511
 
    param.timeout.sec = 0;
512
 
    param.timeout.msec = 2000;
513
 
 
514
 
    thread_quit = PJ_FALSE;
515
 
    g_server.action = ACTION_IGNORE;
516
 
    g_server.send_content_length = PJ_FALSE;
517
 
    g_server.data_size = 4173;
518
 
    g_server.buf_size = 1024;
519
 
 
520
 
    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
521
 
                             &g_server.sock);
522
 
    if (sstatus != PJ_SUCCESS)
523
 
        return -41;
524
 
 
525
 
    pj_sockaddr_in_init(&addr, NULL, 0);
526
 
 
527
 
    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
528
 
    if (sstatus != PJ_SUCCESS)
529
 
        return -43;
530
 
 
531
 
    {
532
 
        pj_sockaddr_in addr;
533
 
        int addr_len = sizeof(addr);
534
 
        sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
535
 
        if (sstatus != PJ_SUCCESS)
536
 
            return -44;
537
 
        g_server.port = pj_sockaddr_in_get_port(&addr);
538
 
        pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
539
 
                         "http://127.0.0.1:%d",
540
 
                         g_server.port);
541
 
        url = pj_str(urlbuf);
542
 
    }
543
 
 
544
 
    sstatus = pj_sock_listen(g_server.sock, 8);
545
 
    if (sstatus != PJ_SUCCESS)
546
 
        return -45;
547
 
 
548
 
    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
549
 
                               0, 0, &g_server.thread);
550
 
    if (sstatus != PJ_SUCCESS)
551
 
        return -47;
552
 
 
553
 
#else
554
 
    pj_cstr(&url, "http://www.google.com.sg");
555
 
    param.timeout.sec = 0;
556
 
    param.timeout.msec = 50;
557
 
#endif
558
 
 
559
 
    pj_http_headers_add_elmt2(&param.headers, (char*)"Accept",
560
 
                             (char*)"image/gif, image/x-xbitmap, image/jpeg, "
561
 
                                    "image/pjpeg, application/x-ms-application,"
562
 
                                    " application/vnd.ms-xpsdocument, "
563
 
                                    "application/xaml+xml, "
564
 
                                    "application/x-ms-xbap, "
565
 
                                    "application/x-shockwave-flash, "
566
 
                                    "application/vnd.ms-excel, "
567
 
                                    "application/vnd.ms-powerpoint, "
568
 
                                    "application/msword, */*");
569
 
    pj_http_headers_add_elmt2(&param.headers, (char*)"Accept-Language",
570
 
                              (char*)"en-sg");
571
 
    pj_http_headers_add_elmt2(&param.headers, (char*)"User-Agent",
572
 
                              (char*)"Mozilla/4.0 (compatible; MSIE 7.0; "
573
 
                                     "Windows NT 6.0; SLCC1; "
574
 
                                     ".NET CLR 2.0.50727; "
575
 
                                     ".NET CLR 3.0.04506)");
576
 
    if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
577
 
                           &param, &hcb, &http_req))
578
 
        return -43;
579
 
 
580
 
    if (pj_http_req_start(http_req))
581
 
        return -45;
582
 
 
583
 
    while (pj_http_req_is_running(http_req)) {
584
 
        pj_time_val delay = {0, 50};
585
 
        pj_ioqueue_poll(ioqueue, &delay);
586
 
        pj_timer_heap_poll(timer_heap, NULL);
587
 
    }
588
 
 
589
 
#ifdef USE_LOCAL_SERVER
590
 
    g_server.action = ACTION_REPLY;
591
 
#endif
592
 
 
593
 
    timeout.sec = 0; timeout.msec = 10000;
594
 
    pj_http_req_set_timeout(http_req, &timeout);
595
 
    if (pj_http_req_start(http_req))
596
 
        return -47;
597
 
 
598
 
    while (pj_http_req_is_running(http_req)) {
599
 
        pj_time_val delay = {0, 50};
600
 
        pj_ioqueue_poll(ioqueue, &delay);
601
 
        pj_timer_heap_poll(timer_heap, NULL);
602
 
    }
603
 
 
604
 
#ifdef USE_LOCAL_SERVER
605
 
    thread_quit = PJ_TRUE;
606
 
    pj_thread_join(g_server.thread);
607
 
    pj_sock_close(g_server.sock);
608
 
#endif
609
 
 
610
 
    pj_http_req_destroy(http_req);
611
 
    pj_ioqueue_destroy(ioqueue);
612
 
    pj_timer_heap_destroy(timer_heap);
613
 
    pj_pool_release(pool);
614
 
 
615
 
    return PJ_SUCCESS;
616
 
}
617
 
 
618
 
/*
619
 
 * PUT request scenario 1: sending the whole data at once
620
 
 */
621
 
int http_client_test_put1()
622
 
{
623
 
    pj_str_t url;
624
 
    pj_http_req_callback hcb;
625
 
    pj_http_req_param param;
626
 
    char *data;
627
 
    int length = 3875;
628
 
    char urlbuf[80];
629
 
 
630
 
    pj_bzero(&hcb, sizeof(hcb));
631
 
    hcb.on_complete = &on_complete;
632
 
    hcb.on_data_read = &on_data_read;
633
 
    hcb.on_response = &on_response;
634
 
 
635
 
    /* Create pool, timer, and ioqueue */
636
 
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
637
 
    if (pj_timer_heap_create(pool, 16, &timer_heap))
638
 
        return -51;
639
 
    if (pj_ioqueue_create(pool, 16, &ioqueue))
640
 
        return -52;
641
 
 
642
 
#ifdef USE_LOCAL_SERVER
643
 
    thread_quit = PJ_FALSE;
644
 
    g_server.action = ACTION_REPLY;
645
 
    g_server.send_content_length = PJ_TRUE;
646
 
    g_server.data_size = 0;
647
 
    g_server.buf_size = 4096;
648
 
 
649
 
    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
650
 
                             &g_server.sock);
651
 
    if (sstatus != PJ_SUCCESS)
652
 
        return -41;
653
 
 
654
 
    pj_sockaddr_in_init(&addr, NULL, 0);
655
 
 
656
 
    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
657
 
    if (sstatus != PJ_SUCCESS)
658
 
        return -43;
659
 
 
660
 
    {
661
 
        pj_sockaddr_in addr;
662
 
        int addr_len = sizeof(addr);
663
 
        sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
664
 
        if (sstatus != PJ_SUCCESS)
665
 
            return -44;
666
 
        g_server.port = pj_sockaddr_in_get_port(&addr);
667
 
        pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
668
 
                         "http://127.0.0.1:%d/test/test.txt",
669
 
                         g_server.port);
670
 
        url = pj_str(urlbuf);
671
 
    }
672
 
 
673
 
    sstatus = pj_sock_listen(g_server.sock, 8);
674
 
    if (sstatus != PJ_SUCCESS)
675
 
        return -45;
676
 
 
677
 
    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
678
 
                               0, 0, &g_server.thread);
679
 
    if (sstatus != PJ_SUCCESS)
680
 
        return -47;
681
 
 
682
 
#else
683
 
    pj_cstr(&url, "http://127.0.0.1:280/test/test.txt");
684
 
 
685
 
#endif
686
 
 
687
 
    pj_http_req_param_default(&param);
688
 
    pj_strset2(&param.method, (char*)"PUT");
689
 
    data = (char*)pj_pool_alloc(pool, length);
690
 
    pj_create_random_string(data, length);
691
 
    pj_ansi_sprintf(data, "PUT test\n");
692
 
    param.reqdata.data = data;
693
 
    param.reqdata.size = length;
694
 
    if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
695
 
                           &param, &hcb, &http_req))
696
 
        return -53;
697
 
 
698
 
    if (pj_http_req_start(http_req))
699
 
        return -55;
700
 
 
701
 
    while (pj_http_req_is_running(http_req)) {
702
 
        pj_time_val delay = {0, 50};
703
 
        pj_ioqueue_poll(ioqueue, &delay);
704
 
        pj_timer_heap_poll(timer_heap, NULL);
705
 
    }
706
 
 
707
 
#ifdef USE_LOCAL_SERVER
708
 
    thread_quit = PJ_TRUE;
709
 
    pj_thread_join(g_server.thread);
710
 
    pj_sock_close(g_server.sock);
711
 
#endif
712
 
 
713
 
    pj_http_req_destroy(http_req);
714
 
    pj_ioqueue_destroy(ioqueue);
715
 
    pj_timer_heap_destroy(timer_heap);
716
 
    pj_pool_release(pool);
717
 
 
718
 
    return PJ_SUCCESS;
719
 
}
720
 
 
721
 
/*
722
 
 * PUT request scenario 2: using on_send_data() callback to
723
 
 * sending the data in chunks
724
 
 */
725
 
int http_client_test_put2()
726
 
{
727
 
    pj_str_t url;
728
 
    pj_http_req_callback hcb;
729
 
    pj_http_req_param param;
730
 
    char urlbuf[80];
731
 
 
732
 
    pj_bzero(&hcb, sizeof(hcb));
733
 
    hcb.on_complete = &on_complete;
734
 
    hcb.on_send_data = &on_send_data;
735
 
    hcb.on_data_read = &on_data_read;
736
 
    hcb.on_response = &on_response;
737
 
 
738
 
    /* Create pool, timer, and ioqueue */
739
 
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
740
 
    if (pj_timer_heap_create(pool, 16, &timer_heap))
741
 
        return -51;
742
 
    if (pj_ioqueue_create(pool, 16, &ioqueue))
743
 
        return -52;
744
 
 
745
 
#ifdef USE_LOCAL_SERVER
746
 
    thread_quit = PJ_FALSE;
747
 
    g_server.action = ACTION_REPLY;
748
 
    g_server.send_content_length = PJ_TRUE;
749
 
    g_server.data_size = 0;
750
 
    g_server.buf_size = 16384;
751
 
 
752
 
    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
753
 
                             &g_server.sock);
754
 
    if (sstatus != PJ_SUCCESS)
755
 
        return -41;
756
 
 
757
 
    pj_sockaddr_in_init(&addr, NULL, 0);
758
 
 
759
 
    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
760
 
    if (sstatus != PJ_SUCCESS)
761
 
        return -43;
762
 
 
763
 
    {
764
 
        pj_sockaddr_in addr;
765
 
        int addr_len = sizeof(addr);
766
 
        sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
767
 
        if (sstatus != PJ_SUCCESS)
768
 
            return -44;
769
 
        g_server.port = pj_sockaddr_in_get_port(&addr);
770
 
        pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
771
 
                         "http://127.0.0.1:%d/test/test2.txt",
772
 
                         g_server.port);
773
 
        url = pj_str(urlbuf);
774
 
    }
775
 
 
776
 
    sstatus = pj_sock_listen(g_server.sock, 8);
777
 
    if (sstatus != PJ_SUCCESS)
778
 
        return -45;
779
 
 
780
 
    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
781
 
                               0, 0, &g_server.thread);
782
 
    if (sstatus != PJ_SUCCESS)
783
 
        return -47;
784
 
 
785
 
#else
786
 
    pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt");
787
 
 
788
 
#endif
789
 
 
790
 
    pj_http_req_param_default(&param);
791
 
    pj_strset2(&param.method, (char*)"PUT");
792
 
    total_size = 15383;
793
 
    send_size = 0;
794
 
    param.reqdata.total_size = total_size;
795
 
    if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
796
 
                           &param, &hcb, &http_req))
797
 
        return -53;
798
 
 
799
 
    if (pj_http_req_start(http_req))
800
 
        return -55;
801
 
 
802
 
    while (pj_http_req_is_running(http_req)) {
803
 
        pj_time_val delay = {0, 50};
804
 
        pj_ioqueue_poll(ioqueue, &delay);
805
 
        pj_timer_heap_poll(timer_heap, NULL);
806
 
    }
807
 
 
808
 
#ifdef USE_LOCAL_SERVER
809
 
    thread_quit = PJ_TRUE;
810
 
    pj_thread_join(g_server.thread);
811
 
    pj_sock_close(g_server.sock);
812
 
#endif
813
 
 
814
 
    pj_http_req_destroy(http_req);
815
 
    pj_ioqueue_destroy(ioqueue);
816
 
    pj_timer_heap_destroy(timer_heap);
817
 
    pj_pool_release(pool);
818
 
 
819
 
    return PJ_SUCCESS;
820
 
}
821
 
 
822
 
int http_client_test_delete()
823
 
{
824
 
    pj_str_t url;
825
 
    pj_http_req_callback hcb;
826
 
    pj_http_req_param param;
827
 
    char urlbuf[80];
828
 
 
829
 
    pj_bzero(&hcb, sizeof(hcb));
830
 
    hcb.on_complete = &on_complete;
831
 
    hcb.on_response = &on_response;
832
 
 
833
 
    /* Create pool, timer, and ioqueue */
834
 
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
835
 
    if (pj_timer_heap_create(pool, 16, &timer_heap))
836
 
        return -61;
837
 
    if (pj_ioqueue_create(pool, 16, &ioqueue))
838
 
        return -62;
839
 
 
840
 
#ifdef USE_LOCAL_SERVER
841
 
    thread_quit = PJ_FALSE;
842
 
    g_server.action = ACTION_REPLY;
843
 
    g_server.send_content_length = PJ_TRUE;
844
 
    g_server.data_size = 0;
845
 
    g_server.buf_size = 1024;
846
 
 
847
 
    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
848
 
                             &g_server.sock);
849
 
    if (sstatus != PJ_SUCCESS)
850
 
        return -41;
851
 
 
852
 
    pj_sockaddr_in_init(&addr, NULL, 0);
853
 
 
854
 
    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
855
 
    if (sstatus != PJ_SUCCESS)
856
 
        return -43;
857
 
 
858
 
    {
859
 
        pj_sockaddr_in addr;
860
 
        int addr_len = sizeof(addr);
861
 
        sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
862
 
        if (sstatus != PJ_SUCCESS)
863
 
            return -44;
864
 
        g_server.port = pj_sockaddr_in_get_port(&addr);
865
 
        pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
866
 
                         "http://127.0.0.1:%d/test/test2.txt",
867
 
                         g_server.port);
868
 
        url = pj_str(urlbuf);
869
 
    }
870
 
 
871
 
    sstatus = pj_sock_listen(g_server.sock, 8);
872
 
    if (sstatus != PJ_SUCCESS)
873
 
        return -45;
874
 
 
875
 
    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
876
 
                               0, 0, &g_server.thread);
877
 
    if (sstatus != PJ_SUCCESS)
878
 
        return -47;
879
 
 
880
 
#else
881
 
    pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt");
882
 
#endif
883
 
 
884
 
    pj_http_req_param_default(&param);
885
 
    pj_strset2(&param.method, (char*)"DELETE");
886
 
    if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
887
 
                           &param, &hcb, &http_req))
888
 
        return -63;
889
 
 
890
 
    if (pj_http_req_start(http_req))
891
 
        return -65;
892
 
 
893
 
    while (pj_http_req_is_running(http_req)) {
894
 
        pj_time_val delay = {0, 50};
895
 
        pj_ioqueue_poll(ioqueue, &delay);
896
 
        pj_timer_heap_poll(timer_heap, NULL);
897
 
    }
898
 
 
899
 
#ifdef USE_LOCAL_SERVER
900
 
    thread_quit = PJ_TRUE;
901
 
    pj_thread_join(g_server.thread);
902
 
    pj_sock_close(g_server.sock);
903
 
#endif
904
 
 
905
 
    pj_http_req_destroy(http_req);
906
 
    pj_ioqueue_destroy(ioqueue);
907
 
    pj_timer_heap_destroy(timer_heap);
908
 
    pj_pool_release(pool);
909
 
 
910
 
    return PJ_SUCCESS;
911
 
}
912
 
 
913
 
int http_client_test()
914
 
{
915
 
    int rc;
916
 
 
917
 
    PJ_LOG(3, (THIS_FILE, "..Testing URL parsing"));
918
 
    rc = parse_url_test();
919
 
    if (rc)
920
 
        return rc;
921
 
 
922
 
    PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 1"));
923
 
    rc = http_client_test1();
924
 
    if (rc)
925
 
        return rc;
926
 
 
927
 
    PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 2"));
928
 
    rc = http_client_test2();
929
 
    if (rc)
930
 
        return rc;
931
 
 
932
 
    PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 1"));
933
 
    rc = http_client_test_put1();
934
 
    if (rc)
935
 
        return rc;
936
 
 
937
 
    PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 2"));
938
 
    rc = http_client_test_put2();
939
 
    if (rc)
940
 
        return rc;
941
 
 
942
 
    PJ_LOG(3, (THIS_FILE, "..Testing DELETE request"));
943
 
    rc = http_client_test_delete();
944
 
    if (rc)
945
 
        return rc;
946
 
 
947
 
    return PJ_SUCCESS;
948
 
}
949
 
 
950
 
#else
951
 
/* To prevent warning about "translation unit is empty"
952
 
 * when this test is disabled.
953
 
 */
954
 
int dummy_http_client_test;
955
 
#endif  /* INCLUDE_HTTP_CLIENT_TEST */