A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

regress_http.c 9.4 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /*
  2. * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #ifdef WIN32
  28. #include <winsock2.h>
  29. #include <windows.h>
  30. #endif
  31. #ifdef HAVE_CONFIG_H
  32. #include "config.h"
  33. #endif
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #ifdef HAVE_SYS_TIME_H
  37. #include <sys/time.h>
  38. #endif
  39. #include <sys/queue.h>
  40. #ifndef WIN32
  41. #include <sys/socket.h>
  42. #include <sys/signal.h>
  43. #include <unistd.h>
  44. #endif
  45. #include <netdb.h>
  46. #include <fcntl.h>
  47. #include <stdlib.h>
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <errno.h>
  51. #include "event.h"
  52. #include "evhttp.h"
  53. #include "log.h"
  54. #include "http-internal.h"
  55. extern int pair[];
  56. extern int test_ok;
  57. static struct evhttp *http;
  58. void http_basic_cb(struct evhttp_request *req, void *arg);
  59. void http_post_cb(struct evhttp_request *req, void *arg);
  60. struct evhttp *
  61. http_setup(short *pport)
  62. {
  63. int i;
  64. struct evhttp *myhttp;
  65. short port = -1;
  66. /* Try a few different ports */
  67. for (i = 0; i < 50; ++i) {
  68. myhttp = evhttp_start("127.0.0.1", 8080 + i);
  69. if (myhttp != NULL) {
  70. port = 8080 + i;
  71. break;
  72. }
  73. }
  74. if (port == -1)
  75. event_errx(1, "Could not start web server");
  76. /* Register a callback for certain types of requests */
  77. evhttp_set_cb(myhttp, "/test", http_basic_cb, NULL);
  78. evhttp_set_cb(myhttp, "/postit", http_post_cb, NULL);
  79. *pport = port;
  80. return (myhttp);
  81. }
  82. int
  83. http_connect(const char *address, u_short port)
  84. {
  85. /* Stupid code for connecting */
  86. struct addrinfo ai, *aitop;
  87. char strport[NI_MAXSERV];
  88. int fd;
  89. memset(&ai, 0, sizeof (ai));
  90. ai.ai_family = AF_INET;
  91. ai.ai_socktype = SOCK_STREAM;
  92. snprintf(strport, sizeof (strport), "%d", port);
  93. if (getaddrinfo(address, strport, &ai, &aitop) != 0) {
  94. event_warn("getaddrinfo");
  95. return (-1);
  96. }
  97. fd = socket(AF_INET, SOCK_STREAM, 0);
  98. if (fd == -1)
  99. event_err(1, "socket failed");
  100. if (connect(fd, aitop->ai_addr, aitop->ai_addrlen) == -1)
  101. event_err(1, "connect failed");
  102. freeaddrinfo(aitop);
  103. return (fd);
  104. }
  105. void
  106. http_readcb(struct bufferevent *bev, void *arg)
  107. {
  108. const char *what = "This is funny";
  109. event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(bev->input)));
  110. if (evbuffer_find(bev->input, what, strlen(what)) != NULL) {
  111. struct evhttp_request *req = evhttp_request_new(NULL, NULL);
  112. req->kind = EVHTTP_RESPONSE;
  113. int done = evhttp_parse_lines(req, bev->input);
  114. if (done == 1 &&
  115. evhttp_find_header(req->input_headers,
  116. "Content-Type") != NULL)
  117. test_ok++;
  118. evhttp_request_free(req);
  119. bufferevent_disable(bev, EV_READ);
  120. event_loopexit(NULL);
  121. }
  122. }
  123. void
  124. http_writecb(struct bufferevent *bev, void *arg)
  125. {
  126. if (EVBUFFER_LENGTH(bev->output) == 0) {
  127. /* enable reading of the reply */
  128. bufferevent_enable(bev, EV_READ);
  129. test_ok++;
  130. }
  131. }
  132. void
  133. http_errorcb(struct bufferevent *bev, short what, void *arg)
  134. {
  135. test_ok = -2;
  136. event_loopexit(NULL);
  137. }
  138. void
  139. http_basic_cb(struct evhttp_request *req, void *arg)
  140. {
  141. event_debug((stderr, "%s: called\n", __func__));
  142. struct evbuffer *evb = evbuffer_new();
  143. evbuffer_add_printf(evb, "This is funny");
  144. evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
  145. evbuffer_free(evb);
  146. }
  147. void
  148. http_basic_test(void)
  149. {
  150. struct bufferevent *bev;
  151. int fd;
  152. char *http_request;
  153. short port = -1;
  154. test_ok = 0;
  155. fprintf(stdout, "Testing Basic HTTP Server: ");
  156. http = http_setup(&port);
  157. fd = http_connect("127.0.0.1", port);
  158. /* Stupid thing to send a request */
  159. bev = bufferevent_new(fd, http_readcb, http_writecb,
  160. http_errorcb, NULL);
  161. http_request =
  162. "GET /test HTTP/1.1\r\n"
  163. "Host: somehost \r\n"
  164. "\r\n";
  165. bufferevent_write(bev, http_request, strlen(http_request));
  166. event_dispatch();
  167. bufferevent_free(bev);
  168. close(fd);
  169. evhttp_free(http);
  170. if (test_ok != 2) {
  171. fprintf(stdout, "FAILED\n");
  172. exit(1);
  173. }
  174. fprintf(stdout, "OK\n");
  175. }
  176. void http_request_done(struct evhttp_request *, void *);
  177. void
  178. http_connection_test(void)
  179. {
  180. short port = -1;
  181. struct evhttp_connection *evcon = NULL;
  182. struct evhttp_request *req = NULL;
  183. test_ok = 0;
  184. fprintf(stdout, "Testing Basic HTTP Connection: ");
  185. http = http_setup(&port);
  186. evcon = evhttp_connection_new("127.0.0.1", port);
  187. if (evcon == NULL) {
  188. fprintf(stdout, "FAILED\n");
  189. exit(1);
  190. }
  191. /*
  192. * At this point, we want to schedule a request to the HTTP
  193. * server using our make request method.
  194. */
  195. req = evhttp_request_new(http_request_done, NULL);
  196. /* Add the information that we care about */
  197. evhttp_add_header(req->output_headers, "Host", "somehost");
  198. /* We give ownership of the request to the connection */
  199. if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
  200. fprintf(stdout, "FAILED\n");
  201. exit(1);
  202. }
  203. event_dispatch();
  204. evhttp_connection_free(evcon);
  205. evhttp_free(http);
  206. if (test_ok != 1) {
  207. fprintf(stdout, "FAILED\n");
  208. exit(1);
  209. }
  210. fprintf(stdout, "OK\n");
  211. }
  212. void
  213. http_request_done(struct evhttp_request *req, void *arg)
  214. {
  215. const char *what = "This is funny";
  216. if (req->response_code != HTTP_OK) {
  217. fprintf(stderr, "FAILED\n");
  218. exit(1);
  219. }
  220. if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) {
  221. fprintf(stderr, "FAILED\n");
  222. exit(1);
  223. }
  224. if (EVBUFFER_LENGTH(req->input_buffer) != strlen(what)) {
  225. fprintf(stderr, "FAILED\n");
  226. exit(1);
  227. }
  228. if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) {
  229. fprintf(stderr, "FAILED\n");
  230. exit(1);
  231. }
  232. test_ok = 1;
  233. event_loopexit(NULL);
  234. }
  235. /*
  236. * HTTP POST test.
  237. */
  238. void http_postrequest_done(struct evhttp_request *, void *);
  239. #define POST_DATA "Okay. Not really printf"
  240. void
  241. http_post_test(void)
  242. {
  243. short port = -1;
  244. struct evhttp_connection *evcon = NULL;
  245. struct evhttp_request *req = NULL;
  246. test_ok = 0;
  247. fprintf(stdout, "Testing HTTP POST Request: ");
  248. http = http_setup(&port);
  249. evcon = evhttp_connection_new("127.0.0.1", port);
  250. if (evcon == NULL) {
  251. fprintf(stdout, "FAILED\n");
  252. exit(1);
  253. }
  254. /*
  255. * At this point, we want to schedule an HTTP POST request
  256. * server using our make request method.
  257. */
  258. req = evhttp_request_new(http_postrequest_done, NULL);
  259. if (req == NULL) {
  260. fprintf(stdout, "FAILED\n");
  261. exit(1);
  262. }
  263. /* Add the information that we care about */
  264. evhttp_add_header(req->output_headers, "Host", "somehost");
  265. evbuffer_add_printf(req->output_buffer, POST_DATA);
  266. if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
  267. fprintf(stdout, "FAILED\n");
  268. exit(1);
  269. }
  270. event_dispatch();
  271. evhttp_connection_free(evcon);
  272. evhttp_free(http);
  273. if (test_ok != 1) {
  274. fprintf(stdout, "FAILED: %d\n", test_ok);
  275. exit(1);
  276. }
  277. fprintf(stdout, "OK\n");
  278. }
  279. void
  280. http_post_cb(struct evhttp_request *req, void *arg)
  281. {
  282. event_debug((stderr, "%s: called\n", __func__));
  283. /* Yes, we are expecting a post request */
  284. if (req->type != EVHTTP_REQ_POST) {
  285. fprintf(stdout, "FAILED (post type)\n");
  286. exit(1);
  287. }
  288. if (EVBUFFER_LENGTH(req->input_buffer) != strlen(POST_DATA)) {
  289. fprintf(stdout, "FAILED (length: %ld vs %ld)\n",
  290. EVBUFFER_LENGTH(req->input_buffer), strlen(POST_DATA));
  291. exit(1);
  292. }
  293. if (memcmp(EVBUFFER_DATA(req->input_buffer), POST_DATA,
  294. strlen(POST_DATA))) {
  295. fprintf(stdout, "FAILED (data)\n");
  296. fprintf(stdout, "Got :%s\n", EVBUFFER_DATA(req->input_buffer));
  297. fprintf(stdout, "Want:%s\n", POST_DATA);
  298. exit(1);
  299. }
  300. struct evbuffer *evb = evbuffer_new();
  301. evbuffer_add_printf(evb, "This is funny");
  302. evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
  303. evbuffer_free(evb);
  304. }
  305. void
  306. http_postrequest_done(struct evhttp_request *req, void *arg)
  307. {
  308. const char *what = "This is funny";
  309. if (req->response_code != HTTP_OK) {
  310. fprintf(stderr, "FAILED (response code)\n");
  311. exit(1);
  312. }
  313. if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) {
  314. fprintf(stderr, "FAILED (content type)\n");
  315. exit(1);
  316. }
  317. if (EVBUFFER_LENGTH(req->input_buffer) != strlen(what)) {
  318. fprintf(stderr, "FAILED (length %ld vs %ld)\n",
  319. EVBUFFER_LENGTH(req->input_buffer), strlen(what));
  320. exit(1);
  321. }
  322. if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) {
  323. fprintf(stderr, "FAILED (data)\n");
  324. exit(1);
  325. }
  326. test_ok = 1;
  327. event_loopexit(NULL);
  328. }
  329. void
  330. http_suite(void)
  331. {
  332. http_basic_test();
  333. http_connection_test();
  334. http_post_test();
  335. }