blob: 8e73650ce3307ced77bc6b0661a351d31404c69e [file] [log] [blame]
Sauw Mingd8435e62010-02-04 18:29:16 +00001/* $Id$ */
2/*
3 * Copyright (C) 2008-2010 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
35static 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
52static pj_bool_t thread_quit;
53static pj_timer_heap_t *timer_heap;
54static pj_ioqueue_t *ioqueue;
55static pj_pool_t *pool;
56static pj_http_req *http_req;
57static pj_bool_t test_cancel = PJ_FALSE;
58static pj_size_t total_size;
59static pj_size_t send_size = 0;
60static pj_status_t sstatus;
61static pj_sockaddr_in addr;
62static int counter = 0;
63
64static int server_thread(void *p)
65{
66 struct server_t *srv = (struct server_t*)p;
Benny Prijonod62947c2010-08-06 08:40:55 +000067 char *pkt = (char*)pj_pool_alloc(pool, srv->buf_size);
Sauw Mingd8435e62010-02-04 18:29:16 +000068 pj_sock_t newsock;
69
70 while (!thread_quit) {
Sauw Mingd8435e62010-02-04 18:29:16 +000071 pj_ssize_t pkt_len;
72 int rc;
73 pj_fd_set_t rset;
Benny Prijonod62947c2010-08-06 08:40:55 +000074 pj_time_val timeout = {0, 500};
Sauw Mingd8435e62010-02-04 18:29:16 +000075
Benny Prijonod62947c2010-08-06 08:40:55 +000076 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 }
Sauw Mingd8435e62010-02-04 18:29:16 +000083
Benny Prijonod62947c2010-08-06 08:40:55 +000084 rc = pj_sock_accept(srv->sock, &newsock, NULL, NULL);
85 if (rc == PJ_SUCCESS) {
86 break;
87 }
88 }
Sauw Mingd8435e62010-02-04 18:29:16 +000089
Benny Prijonod62947c2010-08-06 08:40:55 +000090 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"));
Sauw Mingd8435e62010-02-04 18:29:16 +000099 continue;
100 }
Benny Prijonod62947c2010-08-06 08:40:55 +0000101
102 pkt_len = srv->buf_size;
103 rc = pj_sock_recv(newsock, pkt, &pkt_len, 0);
104 if (rc == PJ_SUCCESS) {
Sauw Mingd8435e62010-02-04 18:29:16 +0000105 break;
Benny Prijonod62947c2010-08-06 08:40:55 +0000106 }
107 }
108
109 if (thread_quit)
110 break;
Sauw Mingd8435e62010-02-04 18:29:16 +0000111
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);
Benny Prijonod62947c2010-08-06 08:40:55 +0000127 rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
128 if (rc != PJ_SUCCESS) {
129 pj_sock_close(newsock);
130 continue;
131 }
Sauw Mingd8435e62010-02-04 18:29:16 +0000132 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';
Benny Prijonod62947c2010-08-06 08:40:55 +0000140 rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
141 if (rc != PJ_SUCCESS)
142 break;
Sauw Mingd8435e62010-02-04 18:29:16 +0000143 }
144 pj_sock_close(newsock);
145 }
146 }
147
148 return 0;
149}
150
151static 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
Sauw Ming63236bb2010-02-05 16:03:29 +0000156 PJ_LOG(5, (THIS_FILE, "\nData received: %d bytes", size));
Sauw Mingd8435e62010-02-04 18:29:16 +0000157 if (size > 0) {
158#ifdef VERBOSE
159 printf("%.*s\n", (int)size, (char *)data);
160#endif
161 }
162}
163
164static 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
Benny Prijono990f6e92010-02-10 10:45:07 +0000177 sdata = (char*)pj_pool_alloc(pool, sendsz);
Sauw Mingd8435e62010-02-04 18:29:16 +0000178 pj_create_random_string(sdata, sendsz);
179 pj_ansi_sprintf(sdata, "\nSegment #%d\n", ++counter);
180 *data = sdata;
181 *size = sendsz;
182
Sauw Ming63236bb2010-02-05 16:03:29 +0000183 PJ_LOG(5, (THIS_FILE, "\nSending data progress: %d out of %d bytes",
Sauw Mingd8435e62010-02-04 18:29:16 +0000184 send_size, total_size));
185}
186
187
188static 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) {
Sauw Ming63236bb2010-02-05 16:03:29 +0000194 PJ_LOG(5, (THIS_FILE, "Request cancelled"));
Sauw Mingd8435e62010-02-04 18:29:16 +0000195 return;
196 } else if (status == PJ_ETIMEDOUT) {
Sauw Ming63236bb2010-02-05 16:03:29 +0000197 PJ_LOG(5, (THIS_FILE, "Request timed out!"));
Sauw Mingd8435e62010-02-04 18:29:16 +0000198 return;
Sauw Ming63236bb2010-02-05 16:03:29 +0000199 } else if (status != PJ_SUCCESS) {
200 PJ_LOG(3, (THIS_FILE, "Error %d", status));
Sauw Mingd8435e62010-02-04 18:29:16 +0000201 return;
202 }
Sauw Ming63236bb2010-02-05 16:03:29 +0000203 PJ_LOG(5, (THIS_FILE, "\nData completed: %d bytes", resp->size));
Sauw Mingd8435e62010-02-04 18:29:16 +0000204 if (resp->size > 0 && resp->data) {
205#ifdef VERBOSE
206 printf("%.*s\n", (int)resp->size, (char *)resp->data);
207#endif
208 }
209}
210
211static 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
Sauw Ming63236bb2010-02-05 16:03:29 +0000220 printf("%.*s, %d, %.*s\n", STR_PREC(resp->version),
221 resp->status_code, STR_PREC(resp->reason));
Sauw Mingd8435e62010-02-04 18:29:16 +0000222 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) {
Benny Prijonod62947c2010-08-06 08:40:55 +0000230 /* Need to delay closing the client socket here, otherwise the
231 * server will get SIGPIPE when sending response.
232 */
233 pj_thread_sleep(100);
Sauw Mingd8435e62010-02-04 18:29:16 +0000234 pj_http_req_cancel(hreq, PJ_TRUE);
235 test_cancel = PJ_FALSE;
236 }
237}
238
239
240pj_status_t parse_url(const char *url)
241{
242 pj_str_t surl;
243 pj_http_url hurl;
244 pj_status_t status;
245
246 pj_cstr(&surl, url);
247 status = pj_http_req_parse_url(&surl, &hurl);
248#ifdef VERBOSE
249 if (!status) {
250 printf("URL: %s\nProtocol: %.*s\nHost: %.*s\nPort: %d\nPath: %.*s\n\n",
251 url, STR_PREC(hurl.protocol), STR_PREC(hurl.host),
252 hurl.port, STR_PREC(hurl.path));
253 } else {
254 }
255#endif
256 return status;
257}
258
259int parse_url_test()
260{
261 /* Simple URL without '/' in the end */
262 if (parse_url("http://www.google.com.sg") != PJ_SUCCESS)
263 return -11;
264 /* Simple URL with port number but without '/' in the end */
265 if (parse_url("http://www.example.com:8080") != PJ_SUCCESS)
266 return -13;
267 /* URL with path */
268 if (parse_url("http://127.0.0.1:280/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6")
269 != PJ_SUCCESS)
270 return -15;
271 /* URL with port and path */
272 if (parse_url("http://teluu.com:81/about-us/") != PJ_SUCCESS)
273 return -17;
274 /* unsupported protocol */
275 if (parse_url("ftp://www.teluu.com") != PJ_ENOTSUP)
276 return -19;
277 /* invalid format */
278 if (parse_url("http:/teluu.com/about-us/") != PJLIB_UTIL_EHTTPINURL)
279 return -21;
280 /* invalid port number */
281 if (parse_url("http://teluu.com:xyz/") != PJLIB_UTIL_EHTTPINPORT)
282 return -23;
283
284 return 0;
285}
286
287/*
288 * GET request scenario 1: using on_response() and on_data_read()
289 * Server replies with content-length. Application cancels the
290 * request upon receiving the response, then start it again.
291 */
292int http_client_test1()
293{
294 pj_str_t url;
295 pj_http_req_callback hcb;
296 pj_http_req_param param;
Benny Prijono2ee684b2010-04-27 08:31:08 +0000297 char urlbuf[80];
Sauw Mingd8435e62010-02-04 18:29:16 +0000298
299 pj_bzero(&hcb, sizeof(hcb));
300 hcb.on_complete = &on_complete;
301 hcb.on_data_read = &on_data_read;
302 hcb.on_response = &on_response;
303 pj_http_req_param_default(&param);
304
305 /* Create pool, timer, and ioqueue */
306 pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
307 if (pj_timer_heap_create(pool, 16, &timer_heap))
308 return -31;
309 if (pj_ioqueue_create(pool, 16, &ioqueue))
310 return -32;
311
312#ifdef USE_LOCAL_SERVER
313
Sauw Mingd8435e62010-02-04 18:29:16 +0000314 thread_quit = PJ_FALSE;
315 g_server.action = ACTION_REPLY;
316 g_server.send_content_length = PJ_TRUE;
317 g_server.data_size = 2970;
Sauw Mingd8435e62010-02-04 18:29:16 +0000318 g_server.buf_size = 1024;
319
320 sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
321 &g_server.sock);
322 if (sstatus != PJ_SUCCESS)
323 return -41;
324
Benny Prijono2ee684b2010-04-27 08:31:08 +0000325 pj_sockaddr_in_init(&addr, NULL, 0);
Sauw Mingd8435e62010-02-04 18:29:16 +0000326
327 sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
328 if (sstatus != PJ_SUCCESS)
329 return -43;
330
Benny Prijono2ee684b2010-04-27 08:31:08 +0000331 {
332 pj_sockaddr_in addr;
333 int addr_len = sizeof(addr);
334 sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
335 if (sstatus != PJ_SUCCESS)
336 return -44;
337 g_server.port = pj_sockaddr_in_get_port(&addr);
338 pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
339 "http://127.0.0.1:%d/about-us/",
340 g_server.port);
341 url = pj_str(urlbuf);
342 }
343
Sauw Mingd8435e62010-02-04 18:29:16 +0000344 sstatus = pj_sock_listen(g_server.sock, 8);
345 if (sstatus != PJ_SUCCESS)
346 return -45;
347
348 sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
349 0, 0, &g_server.thread);
350 if (sstatus != PJ_SUCCESS)
351 return -47;
352
353#else
354 pj_cstr(&url, "http://www.teluu.com/about-us/");
355#endif
356
357 if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
358 &param, &hcb, &http_req))
359 return -33;
360
361 test_cancel = PJ_TRUE;
362 if (pj_http_req_start(http_req))
363 return -35;
364
365 while (pj_http_req_is_running(http_req)) {
366 pj_time_val delay = {0, 50};
367 pj_ioqueue_poll(ioqueue, &delay);
368 pj_timer_heap_poll(timer_heap, NULL);
369 }
370
371 if (pj_http_req_start(http_req))
372 return -37;
373
374 while (pj_http_req_is_running(http_req)) {
375 pj_time_val delay = {0, 50};
376 pj_ioqueue_poll(ioqueue, &delay);
377 pj_timer_heap_poll(timer_heap, NULL);
378 }
379
380#ifdef USE_LOCAL_SERVER
381 thread_quit = PJ_TRUE;
Benny Prijonod62947c2010-08-06 08:40:55 +0000382 pj_thread_join(g_server.thread);
Sauw Mingd8435e62010-02-04 18:29:16 +0000383 pj_sock_close(g_server.sock);
384#endif
385
386 pj_http_req_destroy(http_req);
387 pj_ioqueue_destroy(ioqueue);
388 pj_timer_heap_destroy(timer_heap);
389 pj_pool_release(pool);
390
391 return PJ_SUCCESS;
392}
393
394/*
395 * GET request scenario 2: using on_complete() to get the
396 * complete data. Server does not reply with content-length.
397 * Request timed out, application sets a longer timeout, then
398 * then restart the request.
399 */
400int http_client_test2()
401{
402 pj_str_t url;
403 pj_http_req_callback hcb;
404 pj_http_req_param param;
405 pj_time_val timeout;
Benny Prijono2ee684b2010-04-27 08:31:08 +0000406 char urlbuf[80];
Sauw Mingd8435e62010-02-04 18:29:16 +0000407
408 pj_bzero(&hcb, sizeof(hcb));
409 hcb.on_complete = &on_complete;
410 hcb.on_response = &on_response;
411 pj_http_req_param_default(&param);
412
413 /* Create pool, timer, and ioqueue */
414 pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
415 if (pj_timer_heap_create(pool, 16, &timer_heap))
416 return -41;
417 if (pj_ioqueue_create(pool, 16, &ioqueue))
418 return -42;
419
420#ifdef USE_LOCAL_SERVER
421
422 pj_cstr(&url, "http://127.0.0.1:380");
423 param.timeout.sec = 0;
424 param.timeout.msec = 2000;
425
426 thread_quit = PJ_FALSE;
427 g_server.action = ACTION_IGNORE;
428 g_server.send_content_length = PJ_FALSE;
429 g_server.data_size = 4173;
Sauw Mingd8435e62010-02-04 18:29:16 +0000430 g_server.buf_size = 1024;
431
432 sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
433 &g_server.sock);
434 if (sstatus != PJ_SUCCESS)
435 return -41;
436
Benny Prijono2ee684b2010-04-27 08:31:08 +0000437 pj_sockaddr_in_init(&addr, NULL, 0);
Sauw Mingd8435e62010-02-04 18:29:16 +0000438
439 sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
440 if (sstatus != PJ_SUCCESS)
441 return -43;
442
Benny Prijono2ee684b2010-04-27 08:31:08 +0000443 {
444 pj_sockaddr_in addr;
445 int addr_len = sizeof(addr);
446 sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
447 if (sstatus != PJ_SUCCESS)
448 return -44;
449 g_server.port = pj_sockaddr_in_get_port(&addr);
450 pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
451 "http://127.0.0.1:%d",
452 g_server.port);
453 url = pj_str(urlbuf);
454 }
455
Sauw Mingd8435e62010-02-04 18:29:16 +0000456 sstatus = pj_sock_listen(g_server.sock, 8);
457 if (sstatus != PJ_SUCCESS)
458 return -45;
459
460 sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
461 0, 0, &g_server.thread);
462 if (sstatus != PJ_SUCCESS)
463 return -47;
464
465#else
466 pj_cstr(&url, "http://www.google.com.sg");
467 param.timeout.sec = 0;
468 param.timeout.msec = 50;
469#endif
470
Benny Prijono990f6e92010-02-10 10:45:07 +0000471 pj_http_headers_add_elmt2(&param.headers, (char*)"Accept",
472 (char*)"image/gif, image/x-xbitmap, image/jpeg, "
473 "image/pjpeg, application/x-ms-application,"
474 " application/vnd.ms-xpsdocument, "
475 "application/xaml+xml, "
476 "application/x-ms-xbap, "
477 "application/x-shockwave-flash, "
478 "application/vnd.ms-excel, "
479 "application/vnd.ms-powerpoint, "
480 "application/msword, */*");
481 pj_http_headers_add_elmt2(&param.headers, (char*)"Accept-Language",
482 (char*)"en-sg");
483 pj_http_headers_add_elmt2(&param.headers, (char*)"User-Agent",
484 (char*)"Mozilla/4.0 (compatible; MSIE 7.0; "
485 "Windows NT 6.0; SLCC1; "
486 ".NET CLR 2.0.50727; "
487 ".NET CLR 3.0.04506)");
Sauw Mingd8435e62010-02-04 18:29:16 +0000488 if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
489 &param, &hcb, &http_req))
490 return -43;
491
492 if (pj_http_req_start(http_req))
493 return -45;
494
495 while (pj_http_req_is_running(http_req)) {
496 pj_time_val delay = {0, 50};
497 pj_ioqueue_poll(ioqueue, &delay);
498 pj_timer_heap_poll(timer_heap, NULL);
499 }
500
501#ifdef USE_LOCAL_SERVER
502 g_server.action = ACTION_REPLY;
503#endif
504
505 timeout.sec = 0; timeout.msec = 10000;
506 pj_http_req_set_timeout(http_req, &timeout);
507 if (pj_http_req_start(http_req))
508 return -47;
509
510 while (pj_http_req_is_running(http_req)) {
511 pj_time_val delay = {0, 50};
512 pj_ioqueue_poll(ioqueue, &delay);
513 pj_timer_heap_poll(timer_heap, NULL);
514 }
515
516#ifdef USE_LOCAL_SERVER
517 thread_quit = PJ_TRUE;
Benny Prijonod62947c2010-08-06 08:40:55 +0000518 pj_thread_join(g_server.thread);
Sauw Mingd8435e62010-02-04 18:29:16 +0000519 pj_sock_close(g_server.sock);
520#endif
521
522 pj_http_req_destroy(http_req);
523 pj_ioqueue_destroy(ioqueue);
524 pj_timer_heap_destroy(timer_heap);
525 pj_pool_release(pool);
526
527 return PJ_SUCCESS;
528}
529
530/*
531 * PUT request scenario 1: sending the whole data at once
532 */
533int http_client_test_put1()
534{
535 pj_str_t url;
536 pj_http_req_callback hcb;
537 pj_http_req_param param;
538 char *data;
539 int length = 3875;
Benny Prijono2ee684b2010-04-27 08:31:08 +0000540 char urlbuf[80];
Sauw Mingd8435e62010-02-04 18:29:16 +0000541
542 pj_bzero(&hcb, sizeof(hcb));
543 hcb.on_complete = &on_complete;
544 hcb.on_data_read = &on_data_read;
545 hcb.on_response = &on_response;
546
547 /* Create pool, timer, and ioqueue */
548 pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
549 if (pj_timer_heap_create(pool, 16, &timer_heap))
550 return -51;
551 if (pj_ioqueue_create(pool, 16, &ioqueue))
552 return -52;
553
554#ifdef USE_LOCAL_SERVER
Sauw Mingd8435e62010-02-04 18:29:16 +0000555 thread_quit = PJ_FALSE;
556 g_server.action = ACTION_REPLY;
557 g_server.send_content_length = PJ_TRUE;
558 g_server.data_size = 0;
Sauw Mingd8435e62010-02-04 18:29:16 +0000559 g_server.buf_size = 4096;
560
561 sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
562 &g_server.sock);
563 if (sstatus != PJ_SUCCESS)
564 return -41;
565
Benny Prijono2ee684b2010-04-27 08:31:08 +0000566 pj_sockaddr_in_init(&addr, NULL, 0);
Sauw Mingd8435e62010-02-04 18:29:16 +0000567
568 sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
569 if (sstatus != PJ_SUCCESS)
570 return -43;
571
Benny Prijono2ee684b2010-04-27 08:31:08 +0000572 {
573 pj_sockaddr_in addr;
574 int addr_len = sizeof(addr);
575 sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
576 if (sstatus != PJ_SUCCESS)
577 return -44;
578 g_server.port = pj_sockaddr_in_get_port(&addr);
579 pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
580 "http://127.0.0.1:%d/test/test.txt",
581 g_server.port);
582 url = pj_str(urlbuf);
583 }
584
Sauw Mingd8435e62010-02-04 18:29:16 +0000585 sstatus = pj_sock_listen(g_server.sock, 8);
586 if (sstatus != PJ_SUCCESS)
587 return -45;
588
589 sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
590 0, 0, &g_server.thread);
591 if (sstatus != PJ_SUCCESS)
592 return -47;
593
594#else
595 pj_cstr(&url, "http://127.0.0.1:280/test/test.txt");
596
597#endif
598
599 pj_http_req_param_default(&param);
Benny Prijono990f6e92010-02-10 10:45:07 +0000600 pj_strset2(&param.method, (char*)"PUT");
601 data = (char*)pj_pool_alloc(pool, length);
Sauw Mingd8435e62010-02-04 18:29:16 +0000602 pj_create_random_string(data, length);
603 pj_ansi_sprintf(data, "PUT test\n");
604 param.reqdata.data = data;
605 param.reqdata.size = length;
606 if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
607 &param, &hcb, &http_req))
608 return -53;
609
610 if (pj_http_req_start(http_req))
611 return -55;
612
613 while (pj_http_req_is_running(http_req)) {
614 pj_time_val delay = {0, 50};
615 pj_ioqueue_poll(ioqueue, &delay);
616 pj_timer_heap_poll(timer_heap, NULL);
617 }
618
619#ifdef USE_LOCAL_SERVER
620 thread_quit = PJ_TRUE;
Benny Prijonod62947c2010-08-06 08:40:55 +0000621 pj_thread_join(g_server.thread);
Sauw Mingd8435e62010-02-04 18:29:16 +0000622 pj_sock_close(g_server.sock);
623#endif
624
625 pj_http_req_destroy(http_req);
626 pj_ioqueue_destroy(ioqueue);
627 pj_timer_heap_destroy(timer_heap);
628 pj_pool_release(pool);
629
630 return PJ_SUCCESS;
631}
632
633/*
634 * PUT request scenario 2: using on_send_data() callback to
635 * sending the data in chunks
636 */
637int http_client_test_put2()
638{
639 pj_str_t url;
640 pj_http_req_callback hcb;
641 pj_http_req_param param;
Benny Prijono2ee684b2010-04-27 08:31:08 +0000642 char urlbuf[80];
Sauw Mingd8435e62010-02-04 18:29:16 +0000643
644 pj_bzero(&hcb, sizeof(hcb));
645 hcb.on_complete = &on_complete;
646 hcb.on_send_data = &on_send_data;
647 hcb.on_data_read = &on_data_read;
648 hcb.on_response = &on_response;
649
650 /* Create pool, timer, and ioqueue */
651 pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
652 if (pj_timer_heap_create(pool, 16, &timer_heap))
653 return -51;
654 if (pj_ioqueue_create(pool, 16, &ioqueue))
655 return -52;
656
657#ifdef USE_LOCAL_SERVER
Sauw Mingd8435e62010-02-04 18:29:16 +0000658 thread_quit = PJ_FALSE;
659 g_server.action = ACTION_REPLY;
660 g_server.send_content_length = PJ_TRUE;
661 g_server.data_size = 0;
Sauw Mingd8435e62010-02-04 18:29:16 +0000662 g_server.buf_size = 16384;
663
664 sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
665 &g_server.sock);
666 if (sstatus != PJ_SUCCESS)
667 return -41;
668
Benny Prijono2ee684b2010-04-27 08:31:08 +0000669 pj_sockaddr_in_init(&addr, NULL, 0);
Sauw Mingd8435e62010-02-04 18:29:16 +0000670
671 sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
672 if (sstatus != PJ_SUCCESS)
673 return -43;
674
Benny Prijono2ee684b2010-04-27 08:31:08 +0000675 {
676 pj_sockaddr_in addr;
677 int addr_len = sizeof(addr);
678 sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
679 if (sstatus != PJ_SUCCESS)
680 return -44;
681 g_server.port = pj_sockaddr_in_get_port(&addr);
682 pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
683 "http://127.0.0.1:%d/test/test2.txt",
684 g_server.port);
685 url = pj_str(urlbuf);
686 }
687
Sauw Mingd8435e62010-02-04 18:29:16 +0000688 sstatus = pj_sock_listen(g_server.sock, 8);
689 if (sstatus != PJ_SUCCESS)
690 return -45;
691
692 sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
693 0, 0, &g_server.thread);
694 if (sstatus != PJ_SUCCESS)
695 return -47;
696
697#else
698 pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt");
699
700#endif
701
702 pj_http_req_param_default(&param);
Benny Prijono990f6e92010-02-10 10:45:07 +0000703 pj_strset2(&param.method, (char*)"PUT");
Sauw Mingd8435e62010-02-04 18:29:16 +0000704 total_size = 15383;
705 send_size = 0;
706 param.reqdata.total_size = total_size;
707 if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
708 &param, &hcb, &http_req))
709 return -53;
710
711 if (pj_http_req_start(http_req))
712 return -55;
713
714 while (pj_http_req_is_running(http_req)) {
715 pj_time_val delay = {0, 50};
716 pj_ioqueue_poll(ioqueue, &delay);
717 pj_timer_heap_poll(timer_heap, NULL);
718 }
719
720#ifdef USE_LOCAL_SERVER
721 thread_quit = PJ_TRUE;
Benny Prijonod62947c2010-08-06 08:40:55 +0000722 pj_thread_join(g_server.thread);
Sauw Mingd8435e62010-02-04 18:29:16 +0000723 pj_sock_close(g_server.sock);
724#endif
725
726 pj_http_req_destroy(http_req);
727 pj_ioqueue_destroy(ioqueue);
728 pj_timer_heap_destroy(timer_heap);
729 pj_pool_release(pool);
730
731 return PJ_SUCCESS;
732}
733
734int http_client_test_delete()
735{
736 pj_str_t url;
737 pj_http_req_callback hcb;
738 pj_http_req_param param;
Benny Prijono2ee684b2010-04-27 08:31:08 +0000739 char urlbuf[80];
Sauw Mingd8435e62010-02-04 18:29:16 +0000740
741 pj_bzero(&hcb, sizeof(hcb));
742 hcb.on_complete = &on_complete;
743 hcb.on_response = &on_response;
744
745 /* Create pool, timer, and ioqueue */
746 pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
747 if (pj_timer_heap_create(pool, 16, &timer_heap))
748 return -61;
749 if (pj_ioqueue_create(pool, 16, &ioqueue))
750 return -62;
751
752#ifdef USE_LOCAL_SERVER
Sauw Mingd8435e62010-02-04 18:29:16 +0000753 thread_quit = PJ_FALSE;
754 g_server.action = ACTION_REPLY;
755 g_server.send_content_length = PJ_TRUE;
756 g_server.data_size = 0;
Sauw Mingd8435e62010-02-04 18:29:16 +0000757 g_server.buf_size = 1024;
758
759 sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0,
760 &g_server.sock);
761 if (sstatus != PJ_SUCCESS)
762 return -41;
763
Benny Prijono2ee684b2010-04-27 08:31:08 +0000764 pj_sockaddr_in_init(&addr, NULL, 0);
Sauw Mingd8435e62010-02-04 18:29:16 +0000765
766 sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
767 if (sstatus != PJ_SUCCESS)
768 return -43;
769
Benny Prijono2ee684b2010-04-27 08:31:08 +0000770 {
771 pj_sockaddr_in addr;
772 int addr_len = sizeof(addr);
773 sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
774 if (sstatus != PJ_SUCCESS)
775 return -44;
776 g_server.port = pj_sockaddr_in_get_port(&addr);
777 pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
778 "http://127.0.0.1:%d/test/test2.txt",
779 g_server.port);
780 url = pj_str(urlbuf);
781 }
782
Sauw Mingd8435e62010-02-04 18:29:16 +0000783 sstatus = pj_sock_listen(g_server.sock, 8);
784 if (sstatus != PJ_SUCCESS)
785 return -45;
786
787 sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
788 0, 0, &g_server.thread);
789 if (sstatus != PJ_SUCCESS)
790 return -47;
791
792#else
793 pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt");
794#endif
795
796 pj_http_req_param_default(&param);
Benny Prijono990f6e92010-02-10 10:45:07 +0000797 pj_strset2(&param.method, (char*)"DELETE");
Sauw Mingd8435e62010-02-04 18:29:16 +0000798 if (pj_http_req_create(pool, &url, timer_heap, ioqueue,
799 &param, &hcb, &http_req))
800 return -63;
801
802 if (pj_http_req_start(http_req))
803 return -65;
804
805 while (pj_http_req_is_running(http_req)) {
806 pj_time_val delay = {0, 50};
807 pj_ioqueue_poll(ioqueue, &delay);
808 pj_timer_heap_poll(timer_heap, NULL);
809 }
810
811#ifdef USE_LOCAL_SERVER
812 thread_quit = PJ_TRUE;
Benny Prijonod62947c2010-08-06 08:40:55 +0000813 pj_thread_join(g_server.thread);
Sauw Mingd8435e62010-02-04 18:29:16 +0000814 pj_sock_close(g_server.sock);
815#endif
816
817 pj_http_req_destroy(http_req);
818 pj_ioqueue_destroy(ioqueue);
819 pj_timer_heap_destroy(timer_heap);
820 pj_pool_release(pool);
821
822 return PJ_SUCCESS;
823}
824
825int http_client_test()
826{
827 int rc;
828
829 PJ_LOG(3, (THIS_FILE, "..Testing URL parsing"));
830 rc = parse_url_test();
831 if (rc)
832 return rc;
833
834 PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 1"));
835 rc = http_client_test1();
836 if (rc)
837 return rc;
838
839 PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 2"));
840 rc = http_client_test2();
841 if (rc)
842 return rc;
843
844 PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 1"));
845 rc = http_client_test_put1();
846 if (rc)
847 return rc;
848
849 PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 2"));
850 rc = http_client_test_put2();
851 if (rc)
852 return rc;
853
854 PJ_LOG(3, (THIS_FILE, "..Testing DELETE request"));
855 rc = http_client_test_delete();
856 if (rc)
857 return rc;
858
859 return PJ_SUCCESS;
860}
861
862#else
863/* To prevent warning about "translation unit is empty"
864 * when this test is disabled.
865 */
866int dummy_http_client_test;
867#endif /* INCLUDE_HTTP_CLIENT_TEST */