/* $Id$ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "test.h" #if INCLUDE_HTTP_CLIENT_TEST #define THIS_FILE "test_http" //#define VERBOSE #define STR_PREC(s) (int)s.slen, s.ptr #define USE_LOCAL_SERVER #include #include #define ACTION_REPLY 0 #define ACTION_IGNORE -1 static struct server_t { pj_sock_t sock; pj_uint16_t port; pj_thread_t *thread; /* Action: * 0: reply with the response in resp. * -1: ignore query (to simulate timeout). * other: reply with that error */ int action; pj_bool_t send_content_length; unsigned data_size; unsigned buf_size; } g_server; static pj_bool_t thread_quit; static pj_timer_heap_t *timer_heap; static pj_ioqueue_t *ioqueue; static pj_pool_t *pool; static pj_http_req *http_req; static pj_bool_t test_cancel = PJ_FALSE; static pj_size_t total_size; static pj_size_t send_size = 0; static pj_status_t sstatus; static pj_sockaddr_in addr; static int counter = 0; static int server_thread(void *p) { struct server_t *srv = (struct server_t*)p; char *pkt = (char*)pj_pool_alloc(pool, srv->buf_size); pj_sock_t newsock = PJ_INVALID_SOCKET; while (!thread_quit) { pj_ssize_t pkt_len; int rc; pj_fd_set_t rset; pj_time_val timeout = {0, 500}; while (!thread_quit) { PJ_FD_ZERO(&rset); PJ_FD_SET(srv->sock, &rset); rc = pj_sock_select((int)srv->sock+1, &rset, NULL, NULL, &timeout); if (rc != 1) { continue; } rc = pj_sock_accept(srv->sock, &newsock, NULL, NULL); if (rc == PJ_SUCCESS) { break; } } if (thread_quit) break; while (!thread_quit) { PJ_FD_ZERO(&rset); PJ_FD_SET(newsock, &rset); rc = pj_sock_select((int)newsock+1, &rset, NULL, NULL, &timeout); if (rc != 1) { PJ_LOG(3,("http test", "client timeout")); continue; } pkt_len = srv->buf_size; rc = pj_sock_recv(newsock, pkt, &pkt_len, 0); if (rc == PJ_SUCCESS) { break; } } if (thread_quit) break; /* Simulate network RTT */ pj_thread_sleep(50); if (srv->action == ACTION_IGNORE) { continue; } else if (srv->action == ACTION_REPLY) { pj_size_t send_size = 0; unsigned ctr = 0; pj_ansi_sprintf(pkt, "HTTP/1.0 200 OK\r\n"); if (srv->send_content_length) { pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "Content-Length: %d\r\n", srv->data_size); } pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "\r\n"); pkt_len = pj_ansi_strlen(pkt); rc = pj_sock_send(newsock, pkt, &pkt_len, 0); if (rc != PJ_SUCCESS) { pj_sock_close(newsock); continue; } while (send_size < srv->data_size) { pkt_len = srv->data_size - send_size; if (pkt_len > (signed)srv->buf_size) pkt_len = srv->buf_size; send_size += pkt_len; pj_create_random_string(pkt, pkt_len); pj_ansi_sprintf(pkt, "\nPacket: %d", ++ctr); pkt[pj_ansi_strlen(pkt)] = '\n'; rc = pj_sock_send(newsock, pkt, &pkt_len, 0); if (rc != PJ_SUCCESS) break; } pj_sock_close(newsock); } } return 0; } static void on_data_read(pj_http_req *hreq, void *data, pj_size_t size) { PJ_UNUSED_ARG(hreq); PJ_UNUSED_ARG(data); PJ_LOG(5, (THIS_FILE, "\nData received: %d bytes", size)); if (size > 0) { #ifdef VERBOSE printf("%.*s\n", (int)size, (char *)data); #endif } } static void on_send_data(pj_http_req *hreq, void **data, pj_size_t *size) { char *sdata; pj_size_t sendsz = 8397; PJ_UNUSED_ARG(hreq); if (send_size + sendsz > total_size) { sendsz = total_size - send_size; } send_size += sendsz; sdata = (char*)pj_pool_alloc(pool, sendsz); pj_create_random_string(sdata, sendsz); pj_ansi_sprintf(sdata, "\nSegment #%d\n", ++counter); *data = sdata; *size = sendsz; PJ_LOG(5, (THIS_FILE, "\nSending data progress: %d out of %d bytes", send_size, total_size)); } static void on_complete(pj_http_req *hreq, pj_status_t status, const pj_http_resp *resp) { PJ_UNUSED_ARG(hreq); if (status == PJ_ECANCELLED) { PJ_LOG(5, (THIS_FILE, "Request cancelled")); return; } else if (status == PJ_ETIMEDOUT) { PJ_LOG(5, (THIS_FILE, "Request timed out!")); return; } else if (status != PJ_SUCCESS) { PJ_LOG(3, (THIS_FILE, "Error %d", status)); return; } PJ_LOG(5, (THIS_FILE, "\nData completed: %d bytes", resp->size)); if (resp->size > 0 && resp->data) { #ifdef VERBOSE printf("%.*s\n", (int)resp->size, (char *)resp->data); #endif } } static void on_response(pj_http_req *hreq, const pj_http_resp *resp) { pj_size_t i; PJ_UNUSED_ARG(hreq); PJ_UNUSED_ARG(resp); PJ_UNUSED_ARG(i); #ifdef VERBOSE printf("%.*s, %d, %.*s\n", STR_PREC(resp->version), resp->status_code, STR_PREC(resp->reason)); for (i = 0; i < resp->headers.count; i++) { printf("%.*s : %.*s\n", STR_PREC(resp->headers.header[i].name), STR_PREC(resp->headers.header[i].value)); } #endif if (test_cancel) { /* Need to delay closing the client socket here, otherwise the * server will get SIGPIPE when sending response. */ pj_thread_sleep(100); pj_http_req_cancel(hreq, PJ_TRUE); test_cancel = PJ_FALSE; } } pj_status_t parse_url(const char *url, pj_http_url *hurl) { pj_str_t surl; pj_status_t status; pj_cstr(&surl, url); status = pj_http_req_parse_url(&surl, hurl); #ifdef VERBOSE if (!status) { printf("URL: %s\nProtocol: %.*s\nHost: %.*s\nPort: %d\nPath: %.*s\n\n", url, STR_PREC(hurl->protocol), STR_PREC(hurl->host), hurl->port, STR_PREC(hurl->path)); } else { } #endif return status; } static int parse_url_test() { struct test_data { char *url; pj_status_t result; const char *username; const char *passwd; const char *host; int port; const char *path; } test_data[] = { /* Simple URL without '/' in the end */ {"http://www.pjsip.org", PJ_SUCCESS, "", "", "www.pjsip.org", 80, "/"}, /* Simple URL with port number but without '/' in the end */ {"http://pjsip.org:8080", PJ_SUCCESS, "", "", "pjsip.org", 8080, "/"}, /* URL with path */ {"http://127.0.0.1:280/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6", PJ_SUCCESS, "", "", "127.0.0.1", 280, "/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6"}, /* URL with port and path */ {"http://pjsip.org:81/about-us/", PJ_SUCCESS, "", "", "pjsip.org", 81, "/about-us/"}, /* unsupported protocol */ {"ftp://www.pjsip.org", PJ_ENOTSUP, "", "", "", 80, ""}, /* invalid format */ {"http:/pjsip.org/about-us/", PJLIB_UTIL_EHTTPINURL, "", "", "", 80, ""}, /* invalid port number */ {"http://pjsip.org:xyz/", PJLIB_UTIL_EHTTPINPORT, "", "", "", 80, ""}, /* with username and password */ {"http://user:pass@pjsip.org", PJ_SUCCESS, "user", "pass", "pjsip.org", 80, "/"}, /* password only*/ {"http://:pass@pjsip.org", PJ_SUCCESS, "", "pass", "pjsip.org", 80, "/"}, /* user only*/ {"http://user:@pjsip.org", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/"}, /* empty username and passwd*/ {"http://:@pjsip.org", PJ_SUCCESS, "", "", "pjsip.org", 80, "/"}, /* '@' character in username and path */ {"http://user@pjsip.org/@", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/@"}, /* '@' character in path */ {"http://pjsip.org/@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/@"}, /* '@' character in path */ {"http://pjsip.org/one@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/one@"}, /* Invalid URL */ {"http://:", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http://@", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http:/", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http://", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http:///", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http://@/", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http:///@", PJ_EINVAL, "", "", "", 0, ""}, /* Invalid URL */ {"http://:::", PJ_EINVAL, "", "", "", 0, ""}, }; unsigned i; for (i=0; iurl)); status = parse_url(ptd->url, &hurl); if (status != ptd->result) { PJ_LOG(3,(THIS_FILE, "%d", status)); return -11; } if (status != PJ_SUCCESS) continue; if (pj_strcmp2(&hurl.username, ptd->username)) return -12; if (pj_strcmp2(&hurl.passwd, ptd->passwd)) return -13; if (pj_strcmp2(&hurl.host, ptd->host)) return -14; if (hurl.port != ptd->port) return -15; if (pj_strcmp2(&hurl.path, ptd->path)) return -16; } return 0; } /* * GET request scenario 1: using on_response() and on_data_read() * Server replies with content-length. Application cancels the * request upon receiving the response, then start it again. */ int http_client_test1() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_data_read = &on_data_read; hcb.on_response = &on_response; pj_http_req_param_default(¶m); /* Create pool, timer, and ioqueue */ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL); if (pj_timer_heap_create(pool, 16, &timer_heap)) return -31; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -32; #ifdef USE_LOCAL_SERVER thread_quit = PJ_FALSE; g_server.action = ACTION_REPLY; g_server.send_content_length = PJ_TRUE; g_server.data_size = 2970; g_server.buf_size = 1024; sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &g_server.sock); if (sstatus != PJ_SUCCESS) return -41; pj_sockaddr_in_init(&addr, NULL, 0); sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr)); if (sstatus != PJ_SUCCESS) return -43; { pj_sockaddr_in addr; int addr_len = sizeof(addr); sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len); if (sstatus != PJ_SUCCESS) return -44; g_server.port = pj_sockaddr_in_get_port(&addr); pj_ansi_snprintf(urlbuf, sizeof(urlbuf), "http://127.0.0.1:%d/about-us/", g_server.port); url = pj_str(urlbuf); } sstatus = pj_sock_listen(g_server.sock, 8); if (sstatus != PJ_SUCCESS) return -45; sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server, 0, 0, &g_server.thread); if (sstatus != PJ_SUCCESS) return -47; #else pj_cstr(&url, "http://www.teluu.com/about-us/"); #endif if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -33; test_cancel = PJ_TRUE; if (pj_http_req_start(http_req)) return -35; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } if (pj_http_req_start(http_req)) return -37; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER thread_quit = PJ_TRUE; pj_thread_join(g_server.thread); pj_sock_close(g_server.sock); #endif pj_http_req_destroy(http_req); pj_ioqueue_destroy(ioqueue); pj_timer_heap_destroy(timer_heap); pj_pool_release(pool); return PJ_SUCCESS; } /* * GET request scenario 2: using on_complete() to get the * complete data. Server does not reply with content-length. * Request timed out, application sets a longer timeout, then * then restart the request. */ int http_client_test2() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; pj_time_val timeout; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_response = &on_response; pj_http_req_param_default(¶m); /* Create pool, timer, and ioqueue */ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL); if (pj_timer_heap_create(pool, 16, &timer_heap)) return -41; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -42; #ifdef USE_LOCAL_SERVER pj_cstr(&url, "http://127.0.0.1:380"); param.timeout.sec = 0; param.timeout.msec = 2000; thread_quit = PJ_FALSE; g_server.action = ACTION_IGNORE; g_server.send_content_length = PJ_FALSE; g_server.data_size = 4173; g_server.buf_size = 1024; sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &g_server.sock); if (sstatus != PJ_SUCCESS) return -41; pj_sockaddr_in_init(&addr, NULL, 0); sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr)); if (sstatus != PJ_SUCCESS) return -43; { pj_sockaddr_in addr; int addr_len = sizeof(addr); sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len); if (sstatus != PJ_SUCCESS) return -44; g_server.port = pj_sockaddr_in_get_port(&addr); pj_ansi_snprintf(urlbuf, sizeof(urlbuf), "http://127.0.0.1:%d", g_server.port); url = pj_str(urlbuf); } sstatus = pj_sock_listen(g_server.sock, 8); if (sstatus != PJ_SUCCESS) return -45; sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server, 0, 0, &g_server.thread); if (sstatus != PJ_SUCCESS) return -47; #else pj_cstr(&url, "http://www.google.com.sg"); param.timeout.sec = 0; param.timeout.msec = 50; #endif pj_http_headers_add_elmt2(¶m.headers, (char*)"Accept", (char*)"image/gif, image/x-xbitmap, image/jpeg, " "image/pjpeg, application/x-ms-application," " application/vnd.ms-xpsdocument, " "application/xaml+xml, " "application/x-ms-xbap, " "application/x-shockwave-flash, " "application/vnd.ms-excel, " "application/vnd.ms-powerpoint, " "application/msword, */*"); pj_http_headers_add_elmt2(¶m.headers, (char*)"Accept-Language", (char*)"en-sg"); pj_http_headers_add_elmt2(¶m.headers, (char*)"User-Agent", (char*)"Mozilla/4.0 (compatible; MSIE 7.0; " "Windows NT 6.0; SLCC1; " ".NET CLR 2.0.50727; " ".NET CLR 3.0.04506)"); if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -43; if (pj_http_req_start(http_req)) return -45; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER g_server.action = ACTION_REPLY; #endif timeout.sec = 0; timeout.msec = 10000; pj_http_req_set_timeout(http_req, &timeout); if (pj_http_req_start(http_req)) return -47; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER thread_quit = PJ_TRUE; pj_thread_join(g_server.thread); pj_sock_close(g_server.sock); #endif pj_http_req_destroy(http_req); pj_ioqueue_destroy(ioqueue); pj_timer_heap_destroy(timer_heap); pj_pool_release(pool); return PJ_SUCCESS; } /* * PUT request scenario 1: sending the whole data at once */ int http_client_test_put1() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; char *data; int length = 3875; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_data_read = &on_data_read; hcb.on_response = &on_response; /* Create pool, timer, and ioqueue */ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL); if (pj_timer_heap_create(pool, 16, &timer_heap)) return -51; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -52; #ifdef USE_LOCAL_SERVER thread_quit = PJ_FALSE; g_server.action = ACTION_REPLY; g_server.send_content_length = PJ_TRUE; g_server.data_size = 0; g_server.buf_size = 4096; sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &g_server.sock); if (sstatus != PJ_SUCCESS) return -41; pj_sockaddr_in_init(&addr, NULL, 0); sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr)); if (sstatus != PJ_SUCCESS) return -43; { pj_sockaddr_in addr; int addr_len = sizeof(addr); sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len); if (sstatus != PJ_SUCCESS) return -44; g_server.port = pj_sockaddr_in_get_port(&addr); pj_ansi_snprintf(urlbuf, sizeof(urlbuf), "http://127.0.0.1:%d/test/test.txt", g_server.port); url = pj_str(urlbuf); } sstatus = pj_sock_listen(g_server.sock, 8); if (sstatus != PJ_SUCCESS) return -45; sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server, 0, 0, &g_server.thread); if (sstatus != PJ_SUCCESS) return -47; #else pj_cstr(&url, "http://127.0.0.1:280/test/test.txt"); #endif pj_http_req_param_default(¶m); pj_strset2(¶m.method, (char*)"PUT"); data = (char*)pj_pool_alloc(pool, length); pj_create_random_string(data, length); pj_ansi_sprintf(data, "PUT test\n"); param.reqdata.data = data; param.reqdata.size = length; if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -53; if (pj_http_req_start(http_req)) return -55; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER thread_quit = PJ_TRUE; pj_thread_join(g_server.thread); pj_sock_close(g_server.sock); #endif pj_http_req_destroy(http_req); pj_ioqueue_destroy(ioqueue); pj_timer_heap_destroy(timer_heap); pj_pool_release(pool); return PJ_SUCCESS; } /* * PUT request scenario 2: using on_send_data() callback to * sending the data in chunks */ int http_client_test_put2() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_send_data = &on_send_data; hcb.on_data_read = &on_data_read; hcb.on_response = &on_response; /* Create pool, timer, and ioqueue */ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL); if (pj_timer_heap_create(pool, 16, &timer_heap)) return -51; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -52; #ifdef USE_LOCAL_SERVER thread_quit = PJ_FALSE; g_server.action = ACTION_REPLY; g_server.send_content_length = PJ_TRUE; g_server.data_size = 0; g_server.buf_size = 16384; sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &g_server.sock); if (sstatus != PJ_SUCCESS) return -41; pj_sockaddr_in_init(&addr, NULL, 0); sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr)); if (sstatus != PJ_SUCCESS) return -43; { pj_sockaddr_in addr; int addr_len = sizeof(addr); sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len); if (sstatus != PJ_SUCCESS) return -44; g_server.port = pj_sockaddr_in_get_port(&addr); pj_ansi_snprintf(urlbuf, sizeof(urlbuf), "http://127.0.0.1:%d/test/test2.txt", g_server.port); url = pj_str(urlbuf); } sstatus = pj_sock_listen(g_server.sock, 8); if (sstatus != PJ_SUCCESS) return -45; sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server, 0, 0, &g_server.thread); if (sstatus != PJ_SUCCESS) return -47; #else pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt"); #endif pj_http_req_param_default(¶m); pj_strset2(¶m.method, (char*)"PUT"); total_size = 15383; send_size = 0; param.reqdata.total_size = total_size; if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -53; if (pj_http_req_start(http_req)) return -55; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER thread_quit = PJ_TRUE; pj_thread_join(g_server.thread); pj_sock_close(g_server.sock); #endif pj_http_req_destroy(http_req); pj_ioqueue_destroy(ioqueue); pj_timer_heap_destroy(timer_heap); pj_pool_release(pool); return PJ_SUCCESS; } int http_client_test_delete() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_response = &on_response; /* Create pool, timer, and ioqueue */ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL); if (pj_timer_heap_create(pool, 16, &timer_heap)) return -61; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -62; #ifdef USE_LOCAL_SERVER thread_quit = PJ_FALSE; g_server.action = ACTION_REPLY; g_server.send_content_length = PJ_TRUE; g_server.data_size = 0; g_server.buf_size = 1024; sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &g_server.sock); if (sstatus != PJ_SUCCESS) return -41; pj_sockaddr_in_init(&addr, NULL, 0); sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr)); if (sstatus != PJ_SUCCESS) return -43; { pj_sockaddr_in addr; int addr_len = sizeof(addr); sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len); if (sstatus != PJ_SUCCESS) return -44; g_server.port = pj_sockaddr_in_get_port(&addr); pj_ansi_snprintf(urlbuf, sizeof(urlbuf), "http://127.0.0.1:%d/test/test2.txt", g_server.port); url = pj_str(urlbuf); } sstatus = pj_sock_listen(g_server.sock, 8); if (sstatus != PJ_SUCCESS) return -45; sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server, 0, 0, &g_server.thread); if (sstatus != PJ_SUCCESS) return -47; #else pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt"); #endif pj_http_req_param_default(¶m); pj_strset2(¶m.method, (char*)"DELETE"); if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -63; if (pj_http_req_start(http_req)) return -65; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER thread_quit = PJ_TRUE; pj_thread_join(g_server.thread); pj_sock_close(g_server.sock); #endif pj_http_req_destroy(http_req); pj_ioqueue_destroy(ioqueue); pj_timer_heap_destroy(timer_heap); pj_pool_release(pool); return PJ_SUCCESS; } int http_client_test() { int rc; PJ_LOG(3, (THIS_FILE, "..Testing URL parsing")); rc = parse_url_test(); if (rc) return rc; PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 1")); rc = http_client_test1(); if (rc) return rc; PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 2")); rc = http_client_test2(); if (rc) return rc; PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 1")); rc = http_client_test_put1(); if (rc) return rc; PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 2")); rc = http_client_test_put2(); if (rc) return rc; PJ_LOG(3, (THIS_FILE, "..Testing DELETE request")); rc = http_client_test_delete(); if (rc) return rc; return PJ_SUCCESS; } #else /* To prevent warning about "translation unit is empty" * when this test is disabled. */ int dummy_http_client_test; #endif /* INCLUDE_HTTP_CLIENT_TEST */