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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/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 */