public_server.c 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995
  1. /* Copyright (c) 2015-2016 the Civetweb developers
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. * THE SOFTWARE.
  20. */
  21. #ifdef _MSC_VER
  22. #ifndef _CRT_SECURE_NO_WARNINGS
  23. #define _CRT_SECURE_NO_WARNINGS
  24. #endif
  25. #endif
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <stdarg.h>
  29. #include <time.h>
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #include "public_server.h"
  33. #include <civetweb.h>
  34. #if defined(_WIN32)
  35. #include <Windows.h>
  36. #define test_sleep(x) (Sleep((x)*1000))
  37. #else
  38. #include <unistd.h>
  39. #define test_sleep(x) (sleep(x))
  40. #endif
  41. /* This unit test file uses the excellent Check unit testing library.
  42. * The API documentation is available here:
  43. * http://check.sourceforge.net/doc/check_html/index.html
  44. */
  45. static const char *
  46. locate_path(const char *a_path)
  47. {
  48. static char r_path[256];
  49. #ifdef _WIN32
  50. #ifdef LOCAL_TEST
  51. sprintf(r_path, "%s\\", a_path);
  52. #else
  53. /* Appveyor */
  54. sprintf(r_path, "..\\..\\..\\%s\\", a_path);
  55. /* TODO: the different paths
  56. * used in the different test
  57. * system is an unsolved
  58. * problem. */
  59. #endif
  60. #else
  61. #ifdef LOCAL_TEST
  62. sprintf(r_path, "%s/", a_path);
  63. #else
  64. /* Travis */
  65. sprintf(r_path,
  66. "../../%s/",
  67. a_path); // TODO: fix path in CI test environment
  68. #endif
  69. #endif
  70. return r_path;
  71. }
  72. #define locate_resources() locate_path("resources")
  73. #define locate_test_exes() locate_path("output")
  74. static const char *
  75. locate_ssl_cert(void)
  76. {
  77. static char cert_path[256];
  78. const char *res = locate_resources();
  79. size_t l;
  80. ck_assert(res != NULL);
  81. l = strlen(res);
  82. ck_assert_uint_gt(l, 0);
  83. ck_assert_uint_lt(l, 100); /* assume there is enough space left in our
  84. typical 255 character string buffers */
  85. strcpy(cert_path, res);
  86. strcat(cert_path, "ssl_cert.pem");
  87. return cert_path;
  88. }
  89. static int
  90. wait_not_null(void *volatile *data)
  91. {
  92. int i;
  93. for (i = 0; i < 100; i++) {
  94. mark_point();
  95. test_sleep(1);
  96. if (*data != NULL) {
  97. mark_point();
  98. return 1;
  99. }
  100. }
  101. #if defined(__MINGW32__) || defined(__GNUC__)
  102. #pragma GCC diagnostic push
  103. #pragma GCC diagnostic ignored "-Wunreachable-code"
  104. #endif
  105. #ifdef __clang__
  106. #pragma clang diagnostic push
  107. #pragma clang diagnostic ignored "-Wunreachable-code"
  108. #endif
  109. ck_abort_msg("wait_not_null failed");
  110. return 0;
  111. #ifdef __clang__
  112. #pragma clang diagnostic pop
  113. #endif
  114. #if defined(__MINGW32__) || defined(__GNUC__)
  115. #pragma GCC diagnostic pop
  116. #endif
  117. }
  118. START_TEST(test_the_test_environment)
  119. {
  120. char wd[300];
  121. char buf[500];
  122. FILE *f;
  123. struct stat st;
  124. int ret;
  125. const char *ssl_cert = locate_ssl_cert();
  126. memset(wd, 0, sizeof(wd));
  127. memset(buf, 0, sizeof(buf));
  128. /* Get the current working directory */
  129. #ifdef _WIN32
  130. (void)GetCurrentDirectoryA(sizeof(wd), wd);
  131. wd[sizeof(wd) - 1] = 0;
  132. #else
  133. (void)getcwd(wd, sizeof(wd));
  134. wd[sizeof(wd) - 1] = 0;
  135. #endif
  136. /* Check the pem file */
  137. #ifdef _WIN32
  138. strcpy(buf, wd);
  139. strcat(buf, "\\");
  140. strcat(buf, ssl_cert);
  141. f = fopen(buf, "rb");
  142. #else
  143. strcpy(buf, wd);
  144. strcat(buf, "/");
  145. strcat(buf, ssl_cert);
  146. f = fopen(buf, "r");
  147. #endif
  148. if (f) {
  149. fclose(f);
  150. } else {
  151. fprintf(stderr, "%s not found", buf);
  152. }
  153. /* Check the test dir */
  154. #ifdef _WIN32
  155. strcpy(buf, wd);
  156. strcat(buf, "\\test");
  157. #else
  158. strcpy(buf, wd);
  159. strcat(buf, "/test");
  160. #endif
  161. memset(&st, 0, sizeof(st));
  162. ret = stat(buf, &st);
  163. if (ret) {
  164. fprintf(stderr, "%s not found", buf);
  165. }
  166. }
  167. END_TEST
  168. static void *threading_data;
  169. static void *
  170. test_thread_func_t(void *param)
  171. {
  172. ck_assert_ptr_eq(param, &threading_data);
  173. ck_assert_ptr_eq(threading_data, NULL);
  174. threading_data = &threading_data;
  175. return NULL;
  176. }
  177. START_TEST(test_threading)
  178. {
  179. int ok;
  180. threading_data = NULL;
  181. ok = mg_start_thread(test_thread_func_t, &threading_data);
  182. ck_assert_int_eq(ok, 0);
  183. wait_not_null(&threading_data);
  184. ck_assert_ptr_eq(threading_data, &threading_data);
  185. }
  186. END_TEST
  187. static int
  188. log_msg_func(const struct mg_connection *conn, const char *message)
  189. {
  190. struct mg_context *ctx;
  191. char *ud;
  192. ck_assert(conn != NULL);
  193. ctx = mg_get_context(conn);
  194. ck_assert(ctx != NULL);
  195. ud = (char *)mg_get_user_data(ctx);
  196. strncpy(ud, message, 255);
  197. ud[255] = 0;
  198. return 1;
  199. }
  200. START_TEST(test_mg_start_stop_http_server)
  201. {
  202. struct mg_context *ctx;
  203. const char *OPTIONS[] = {
  204. #if !defined(NO_FILES)
  205. "document_root",
  206. ".",
  207. #endif
  208. "listening_ports",
  209. "8080",
  210. NULL,
  211. };
  212. size_t ports_cnt;
  213. int ports[16];
  214. int ssl[16];
  215. struct mg_callbacks callbacks;
  216. char errmsg[256];
  217. struct mg_connection *client_conn;
  218. char client_err[256];
  219. const struct mg_request_info *client_ri;
  220. int client_res;
  221. memset(ports, 0, sizeof(ports));
  222. memset(ssl, 0, sizeof(ssl));
  223. memset(&callbacks, 0, sizeof(callbacks));
  224. memset(errmsg, 0, sizeof(errmsg));
  225. callbacks.log_message = log_msg_func;
  226. mark_point();
  227. ctx = mg_start(&callbacks, (void *)errmsg, OPTIONS);
  228. test_sleep(1);
  229. ck_assert_str_eq(errmsg, "");
  230. ck_assert(ctx != NULL);
  231. ports_cnt = mg_get_ports(ctx, 16, ports, ssl);
  232. ck_assert_uint_eq(ports_cnt, 1);
  233. ck_assert_int_eq(ports[0], 8080);
  234. ck_assert_int_eq(ssl[0], 0);
  235. ck_assert_int_eq(ports[1], 0);
  236. ck_assert_int_eq(ssl[1], 0);
  237. test_sleep(1);
  238. memset(client_err, 0, sizeof(client_err));
  239. client_conn =
  240. mg_connect_client("127.0.0.1", 8080, 0, client_err, sizeof(client_err));
  241. ck_assert(client_conn != NULL);
  242. ck_assert_str_eq(client_err, "");
  243. mg_printf(client_conn, "GET / HTTP/1.0\r\n\r\n");
  244. client_res =
  245. mg_get_response(client_conn, client_err, sizeof(client_err), 10000);
  246. ck_assert_int_ge(client_res, 0);
  247. ck_assert_str_eq(client_err, "");
  248. client_ri = mg_get_request_info(client_conn);
  249. ck_assert(client_ri != NULL);
  250. #if defined(NO_FILES)
  251. ck_assert_str_eq(client_ri->uri, "404");
  252. #else
  253. ck_assert_str_eq(client_ri->uri, "200");
  254. /* TODO: ck_assert_str_eq(client_ri->request_method, "HTTP/1.0"); */
  255. client_res = (int)mg_read(client_conn, client_err, sizeof(client_err));
  256. ck_assert_int_gt(client_res, 0);
  257. ck_assert_int_le(client_res, sizeof(client_err));
  258. #endif
  259. mg_close_connection(client_conn);
  260. test_sleep(1);
  261. mg_stop(ctx);
  262. }
  263. END_TEST
  264. START_TEST(test_mg_start_stop_https_server)
  265. {
  266. #ifndef NO_SSL
  267. struct mg_context *ctx;
  268. size_t ports_cnt;
  269. int ports[16];
  270. int ssl[16];
  271. struct mg_callbacks callbacks;
  272. char errmsg[256];
  273. const char *OPTIONS[8]; /* initializer list here is rejected by CI test */
  274. int opt_idx = 0;
  275. const char *ssl_cert = locate_ssl_cert();
  276. struct mg_connection *client_conn;
  277. char client_err[256];
  278. const struct mg_request_info *client_ri;
  279. int client_res;
  280. ck_assert(ssl_cert != NULL);
  281. memset((void *)OPTIONS, 0, sizeof(OPTIONS));
  282. #if !defined(NO_FILES)
  283. OPTIONS[opt_idx++] = "document_root";
  284. OPTIONS[opt_idx++] = ".";
  285. #endif
  286. OPTIONS[opt_idx++] = "listening_ports";
  287. OPTIONS[opt_idx++] = "8080r,8443s";
  288. OPTIONS[opt_idx++] = "ssl_certificate";
  289. OPTIONS[opt_idx++] = ssl_cert;
  290. ck_assert_int_le(opt_idx, (int)(sizeof(OPTIONS) / sizeof(OPTIONS[0])));
  291. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
  292. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);
  293. memset(ports, 0, sizeof(ports));
  294. memset(ssl, 0, sizeof(ssl));
  295. memset(&callbacks, 0, sizeof(callbacks));
  296. memset(errmsg, 0, sizeof(errmsg));
  297. callbacks.log_message = log_msg_func;
  298. mark_point();
  299. ctx = mg_start(&callbacks, (void *)errmsg, OPTIONS);
  300. test_sleep(1);
  301. ck_assert_str_eq(errmsg, "");
  302. ck_assert(ctx != NULL);
  303. ports_cnt = mg_get_ports(ctx, 16, ports, ssl);
  304. ck_assert_uint_eq(ports_cnt, 2);
  305. ck_assert_int_eq(ports[0], 8080);
  306. ck_assert_int_eq(ssl[0], 0);
  307. ck_assert_int_eq(ports[1], 8443);
  308. ck_assert_int_eq(ssl[1], 1);
  309. ck_assert_int_eq(ports[2], 0);
  310. ck_assert_int_eq(ssl[2], 0);
  311. test_sleep(1);
  312. memset(client_err, 0, sizeof(client_err));
  313. client_conn =
  314. mg_connect_client("127.0.0.1", 8443, 1, client_err, sizeof(client_err));
  315. ck_assert(client_conn != NULL);
  316. ck_assert_str_eq(client_err, "");
  317. mg_printf(client_conn, "GET / HTTP/1.0\r\n\r\n");
  318. client_res =
  319. mg_get_response(client_conn, client_err, sizeof(client_err), 10000);
  320. ck_assert_int_ge(client_res, 0);
  321. ck_assert_str_eq(client_err, "");
  322. client_ri = mg_get_request_info(client_conn);
  323. ck_assert(client_ri != NULL);
  324. #if defined(NO_FILES)
  325. ck_assert_str_eq(client_ri->uri, "404");
  326. #else
  327. ck_assert_str_eq(client_ri->uri, "200");
  328. /* TODO: ck_assert_str_eq(client_ri->request_method, "HTTP/1.0"); */
  329. client_res = (int)mg_read(client_conn, client_err, sizeof(client_err));
  330. ck_assert_int_gt(client_res, 0);
  331. ck_assert_int_le(client_res, sizeof(client_err));
  332. #endif
  333. mg_close_connection(client_conn);
  334. test_sleep(1);
  335. mg_stop(ctx);
  336. #endif
  337. }
  338. END_TEST
  339. START_TEST(test_mg_server_and_client_tls)
  340. {
  341. #ifndef NO_SSL
  342. struct mg_context *ctx;
  343. int ports_cnt;
  344. struct mg_server_ports ports[16];
  345. struct mg_callbacks callbacks;
  346. char errmsg[256];
  347. struct mg_connection *client_conn;
  348. char client_err[256];
  349. const struct mg_request_info *client_ri;
  350. int client_res;
  351. struct mg_client_options client_options;
  352. const char *OPTIONS[32]; /* initializer list here is rejected by CI test */
  353. int opt_idx = 0;
  354. char server_cert[256];
  355. char client_cert[256];
  356. const char *res_dir = locate_resources();
  357. ck_assert(res_dir != NULL);
  358. strcpy(server_cert, res_dir);
  359. strcpy(client_cert, res_dir);
  360. #ifdef _WIN32
  361. strcat(server_cert, "cert\\server.pem");
  362. strcat(client_cert, "cert\\client.pem");
  363. #else
  364. strcat(server_cert, "cert/server.pem");
  365. strcat(client_cert, "cert/client.pem");
  366. #endif
  367. memset((void *)OPTIONS, 0, sizeof(OPTIONS));
  368. #if !defined(NO_FILES)
  369. OPTIONS[opt_idx++] = "document_root";
  370. OPTIONS[opt_idx++] = ".";
  371. #endif
  372. OPTIONS[opt_idx++] = "listening_ports";
  373. OPTIONS[opt_idx++] = "8080r,8443s";
  374. OPTIONS[opt_idx++] = "ssl_certificate";
  375. OPTIONS[opt_idx++] = server_cert;
  376. OPTIONS[opt_idx++] = "ssl_verify_peer";
  377. OPTIONS[opt_idx++] = "yes";
  378. OPTIONS[opt_idx++] = "ssl_ca_file";
  379. OPTIONS[opt_idx++] = client_cert;
  380. ck_assert_int_le(opt_idx, (int)(sizeof(OPTIONS) / sizeof(OPTIONS[0])));
  381. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
  382. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);
  383. memset(ports, 0, sizeof(ports));
  384. memset(&callbacks, 0, sizeof(callbacks));
  385. memset(errmsg, 0, sizeof(errmsg));
  386. callbacks.log_message = log_msg_func;
  387. mark_point();
  388. ctx = mg_start(&callbacks, (void *)errmsg, OPTIONS);
  389. test_sleep(1);
  390. ck_assert_str_eq(errmsg, "");
  391. ck_assert(ctx != NULL);
  392. ports_cnt = mg_get_server_ports(ctx, 16, ports);
  393. ck_assert_int_eq(ports_cnt, 2);
  394. ck_assert_int_eq(ports[0].protocol, 1);
  395. ck_assert_int_eq(ports[0].port, 8080);
  396. ck_assert_int_eq(ports[0].is_ssl, 0);
  397. ck_assert_int_eq(ports[0].is_redirect, 1);
  398. ck_assert_int_eq(ports[1].protocol, 1);
  399. ck_assert_int_eq(ports[1].port, 8443);
  400. ck_assert_int_eq(ports[1].is_ssl, 1);
  401. ck_assert_int_eq(ports[1].is_redirect, 0);
  402. ck_assert_int_eq(ports[2].protocol, 0);
  403. ck_assert_int_eq(ports[2].port, 0);
  404. ck_assert_int_eq(ports[2].is_ssl, 0);
  405. ck_assert_int_eq(ports[2].is_redirect, 0);
  406. test_sleep(1);
  407. memset(client_err, 0, sizeof(client_err));
  408. client_conn =
  409. mg_connect_client("127.0.0.1", 8443, 1, client_err, sizeof(client_err));
  410. ck_assert(client_conn == NULL);
  411. ck_assert_str_ne(client_err, "");
  412. memset(client_err, 0, sizeof(client_err));
  413. memset(&client_options, 0, sizeof(client_options));
  414. client_options.host = "127.0.0.1";
  415. client_options.port = 8443;
  416. client_options.client_cert = client_cert;
  417. client_options.server_cert = server_cert;
  418. client_conn = mg_connect_client_secure(&client_options,
  419. client_err,
  420. sizeof(client_err));
  421. ck_assert(client_conn != NULL);
  422. ck_assert_str_eq(client_err, "");
  423. mg_printf(client_conn, "GET / HTTP/1.0\r\n\r\n");
  424. client_res =
  425. mg_get_response(client_conn, client_err, sizeof(client_err), 10000);
  426. ck_assert_int_ge(client_res, 0);
  427. ck_assert_str_eq(client_err, "");
  428. client_ri = mg_get_request_info(client_conn);
  429. ck_assert(client_ri != NULL);
  430. #if defined(NO_FILES)
  431. ck_assert_str_eq(client_ri->uri, "404");
  432. #else
  433. ck_assert_str_eq(client_ri->uri, "200");
  434. /* TODO: ck_assert_str_eq(client_ri->request_method, "HTTP/1.0"); */
  435. client_res = (int)mg_read(client_conn, client_err, sizeof(client_err));
  436. ck_assert_int_gt(client_res, 0);
  437. ck_assert_int_le(client_res, sizeof(client_err));
  438. #endif
  439. mg_close_connection(client_conn);
  440. /* TODO: A client API using a client certificate is missing */
  441. test_sleep(1);
  442. mg_stop(ctx);
  443. #endif
  444. }
  445. END_TEST
  446. static struct mg_context *g_ctx;
  447. static int
  448. request_test_handler(struct mg_connection *conn, void *cbdata)
  449. {
  450. int i;
  451. char chunk_data[32];
  452. const struct mg_request_info *ri;
  453. struct mg_context *ctx;
  454. void *ud, *cud;
  455. ctx = mg_get_context(conn);
  456. ud = mg_get_user_data(ctx);
  457. ri = mg_get_request_info(conn);
  458. ck_assert(ri != NULL);
  459. ck_assert(ctx == g_ctx);
  460. ck_assert(ud == &g_ctx);
  461. mg_set_user_connection_data(conn, (void *)6543);
  462. cud = mg_get_user_connection_data(conn);
  463. ck_assert_ptr_eq((void *)cud, (void *)6543);
  464. ck_assert_ptr_eq((void *)cbdata, (void *)7);
  465. strcpy(chunk_data, "123456789A123456789B123456789C");
  466. mg_printf(conn,
  467. "HTTP/1.1 200 OK\r\n"
  468. "Transfer-Encoding: chunked\r\n"
  469. "Content-Type: text/plain\r\n\r\n");
  470. for (i = 1; i <= 10; i++) {
  471. mg_printf(conn, "%x\r\n", i);
  472. mg_write(conn, chunk_data, (unsigned)i);
  473. mg_printf(conn, "\r\n");
  474. }
  475. mg_printf(conn, "0\r\n\r\n");
  476. return 1;
  477. }
  478. #ifdef USE_WEBSOCKET
  479. /****************************************************************************/
  480. /* WEBSOCKET SERVER */
  481. /****************************************************************************/
  482. static const char *websocket_welcome_msg = "websocket welcome\n";
  483. static const size_t websocket_welcome_msg_len =
  484. 18 /* strlen(websocket_welcome_msg) */;
  485. static const char *websocket_goodbye_msg = "websocket bye\n";
  486. static const size_t websocket_goodbye_msg_len =
  487. 14 /* strlen(websocket_goodbye_msg) */;
  488. static int
  489. websock_server_connect(const struct mg_connection *conn, void *udata)
  490. {
  491. (void)conn;
  492. ck_assert_ptr_eq((void *)udata, (void *)7531);
  493. printf("Server: Websocket connected\n");
  494. return 0; /* return 0 to accept every connection */
  495. }
  496. static void
  497. websock_server_ready(struct mg_connection *conn, void *udata)
  498. {
  499. ck_assert_ptr_eq((void *)udata, (void *)7531);
  500. printf("Server: Websocket ready\n");
  501. /* Send websocket welcome message */
  502. mg_lock_connection(conn);
  503. mg_websocket_write(conn,
  504. WEBSOCKET_OPCODE_TEXT,
  505. websocket_welcome_msg,
  506. websocket_welcome_msg_len);
  507. mg_unlock_connection(conn);
  508. printf("Server: Websocket ready X\n");
  509. }
  510. static int
  511. websock_server_data(struct mg_connection *conn,
  512. int bits,
  513. char *data,
  514. size_t data_len,
  515. void *udata)
  516. {
  517. (void)bits;
  518. ck_assert_ptr_eq((void *)udata, (void *)7531);
  519. printf("Server: Got %u bytes from the client\n", (unsigned)data_len);
  520. if (data_len == 3 && !memcmp(data, "bye", 3)) {
  521. /* Send websocket goodbye message */
  522. mg_lock_connection(conn);
  523. mg_websocket_write(conn,
  524. WEBSOCKET_OPCODE_TEXT,
  525. websocket_goodbye_msg,
  526. websocket_goodbye_msg_len);
  527. mg_unlock_connection(conn);
  528. } else if (data_len == 5 && !memcmp(data, "data1", 5)) {
  529. mg_lock_connection(conn);
  530. mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, "ok1", 3);
  531. mg_unlock_connection(conn);
  532. } else if (data_len == 5 && !memcmp(data, "data2", 5)) {
  533. mg_lock_connection(conn);
  534. mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, "ok 2", 4);
  535. mg_unlock_connection(conn);
  536. } else if (data_len == 5 && !memcmp(data, "data3", 5)) {
  537. mg_lock_connection(conn);
  538. mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, "ok - 3", 6);
  539. mg_unlock_connection(conn);
  540. } else {
  541. #if defined(__MINGW32__) || defined(__GNUC__)
  542. #pragma GCC diagnostic push
  543. #pragma GCC diagnostic ignored "-Wunreachable-code"
  544. #endif
  545. #ifdef __clang__
  546. #pragma clang diagnostic push
  547. #pragma clang diagnostic ignored "-Wunreachable-code"
  548. #endif
  549. ck_abort_msg("Got unexpected message from websocket client");
  550. return 0;
  551. #ifdef __clang__
  552. #pragma clang diagnostic pop
  553. #endif
  554. #if defined(__MINGW32__) || defined(__GNUC__)
  555. #pragma GCC diagnostic pop
  556. #endif
  557. }
  558. return 1; /* return 1 to keep the connetion open */
  559. }
  560. static void
  561. websock_server_close(const struct mg_connection *conn, void *udata)
  562. {
  563. (void)conn;
  564. ck_assert_ptr_eq((void *)udata, (void *)7531);
  565. printf("Server: Close connection\n");
  566. /* Can not send a websocket goodbye message here - the connection is already
  567. * closed */
  568. }
  569. /****************************************************************************/
  570. /* WEBSOCKET CLIENT */
  571. /****************************************************************************/
  572. struct tclient_data {
  573. void *data;
  574. size_t len;
  575. int closed;
  576. };
  577. static int
  578. websocket_client_data_handler(struct mg_connection *conn,
  579. int flags,
  580. char *data,
  581. size_t data_len,
  582. void *user_data)
  583. {
  584. struct mg_context *ctx = mg_get_context(conn);
  585. struct tclient_data *pclient_data =
  586. (struct tclient_data *)mg_get_user_data(ctx);
  587. (void)user_data; /* TODO: check this */
  588. ck_assert(pclient_data != NULL);
  589. ck_assert_int_eq(flags, (int)(128 | 1));
  590. printf("Client received data from server: ");
  591. fwrite(data, 1, data_len, stdout);
  592. printf("\n");
  593. pclient_data->data = malloc(data_len);
  594. ck_assert(pclient_data->data != NULL);
  595. memcpy(pclient_data->data, data, data_len);
  596. pclient_data->len = data_len;
  597. return 1;
  598. }
  599. static void
  600. websocket_client_close_handler(const struct mg_connection *conn,
  601. void *user_data)
  602. {
  603. struct mg_context *ctx = mg_get_context(conn);
  604. struct tclient_data *pclient_data =
  605. (struct tclient_data *)mg_get_user_data(ctx);
  606. (void)user_data; /* TODO: check this */
  607. ck_assert(pclient_data != NULL);
  608. printf("Client: Close handler\n");
  609. pclient_data->closed++;
  610. }
  611. #endif
  612. START_TEST(test_request_handlers)
  613. {
  614. char ebuf[100];
  615. struct mg_context *ctx;
  616. struct mg_connection *client_conn;
  617. const struct mg_request_info *ri;
  618. char uri[64];
  619. char buf[1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 8];
  620. const char *expected =
  621. "112123123412345123456123456712345678123456789123456789A";
  622. int i;
  623. const char *request = "GET /U7 HTTP/1.0\r\n\r\n";
  624. #if defined(USE_IPV6) && defined(NO_SSL)
  625. const char *HTTP_PORT = "8084,[::]:8086";
  626. short ipv4_port = 8084;
  627. short ipv6_port = 8086;
  628. #elif !defined(USE_IPV6) && defined(NO_SSL)
  629. const char *HTTP_PORT = "8084";
  630. short ipv4_port = 8084;
  631. #elif defined(USE_IPV6) && !defined(NO_SSL)
  632. const char *HTTP_PORT = "8084,[::]:8086,8194r,[::]:8196r,8094s,[::]:8096s";
  633. short ipv4_port = 8084;
  634. short ipv4s_port = 8094;
  635. short ipv4r_port = 8194;
  636. short ipv6_port = 8086;
  637. short ipv6s_port = 8096;
  638. short ipv6r_port = 8196;
  639. #elif !defined(USE_IPV6) && !defined(NO_SSL)
  640. const char *HTTP_PORT = "8084,8194r,8094s";
  641. short ipv4_port = 8084;
  642. short ipv4s_port = 8094;
  643. short ipv4r_port = 8194;
  644. #endif
  645. const char *OPTIONS[8]; /* initializer list here is rejected by CI test */
  646. const char *opt;
  647. FILE *f;
  648. const char *plain_file_content;
  649. const char *encoded_file_content;
  650. const char *cgi_script_content;
  651. const char *expected_cgi_result;
  652. int opt_idx = 0;
  653. #if !defined(NO_SSL)
  654. const char *ssl_cert = locate_ssl_cert();
  655. #endif
  656. #if defined(USE_WEBSOCKET)
  657. struct tclient_data ws_client1_data = {NULL, 0, 0};
  658. struct tclient_data ws_client2_data = {NULL, 0, 0};
  659. struct tclient_data ws_client3_data = {NULL, 0, 0};
  660. struct mg_connection *ws_client1_conn = NULL;
  661. struct mg_connection *ws_client2_conn = NULL;
  662. struct mg_connection *ws_client3_conn = NULL;
  663. #endif
  664. char cmd_buf[256];
  665. memset((void *)OPTIONS, 0, sizeof(OPTIONS));
  666. OPTIONS[opt_idx++] = "listening_ports";
  667. OPTIONS[opt_idx++] = HTTP_PORT;
  668. #if !defined(NO_FILES)
  669. OPTIONS[opt_idx++] = "document_root";
  670. OPTIONS[opt_idx++] = ".";
  671. #endif
  672. #ifndef NO_SSL
  673. ck_assert(ssl_cert != NULL);
  674. OPTIONS[opt_idx++] = "ssl_certificate";
  675. OPTIONS[opt_idx++] = ssl_cert;
  676. #endif
  677. ck_assert_int_le(opt_idx, (int)(sizeof(OPTIONS) / sizeof(OPTIONS[0])));
  678. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
  679. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);
  680. mark_point();
  681. ctx = mg_start(NULL, &g_ctx, OPTIONS);
  682. ck_assert(ctx != NULL);
  683. g_ctx = ctx;
  684. opt = mg_get_option(ctx, "listening_ports");
  685. ck_assert_str_eq(opt, HTTP_PORT);
  686. opt = mg_get_option(ctx, "cgi_environment");
  687. ck_assert_str_eq(opt, "");
  688. opt = mg_get_option(ctx, "unknown_option_name");
  689. ck_assert(opt == NULL);
  690. for (i = 0; i < 1000; i++) {
  691. sprintf(uri, "/U%u", i);
  692. mg_set_request_handler(ctx, uri, request_test_handler, NULL);
  693. }
  694. for (i = 500; i < 800; i++) {
  695. sprintf(uri, "/U%u", i);
  696. mg_set_request_handler(ctx, uri, NULL, (void *)1);
  697. }
  698. for (i = 600; i >= 0; i--) {
  699. sprintf(uri, "/U%u", i);
  700. mg_set_request_handler(ctx, uri, NULL, (void *)2);
  701. }
  702. for (i = 750; i <= 1000; i++) {
  703. sprintf(uri, "/U%u", i);
  704. mg_set_request_handler(ctx, uri, NULL, (void *)3);
  705. }
  706. for (i = 5; i < 9; i++) {
  707. sprintf(uri, "/U%u", i);
  708. mg_set_request_handler(ctx,
  709. uri,
  710. request_test_handler,
  711. (void *)(ptrdiff_t)i);
  712. }
  713. #ifdef USE_WEBSOCKET
  714. mg_set_websocket_handler(ctx,
  715. "/websocket",
  716. websock_server_connect,
  717. websock_server_ready,
  718. websock_server_data,
  719. websock_server_close,
  720. (void *)7531);
  721. #endif
  722. /* Try to load non existing file */
  723. client_conn = mg_download("localhost",
  724. ipv4_port,
  725. 0,
  726. ebuf,
  727. sizeof(ebuf),
  728. "%s",
  729. "GET /file/not/found HTTP/1.0\r\n\r\n");
  730. ck_assert(client_conn != NULL);
  731. ri = mg_get_request_info(client_conn);
  732. ck_assert(ri != NULL);
  733. ck_assert_str_eq(ri->uri, "404");
  734. mg_close_connection(client_conn);
  735. /* Get data from callback */
  736. client_conn = mg_download(
  737. "localhost", ipv4_port, 0, ebuf, sizeof(ebuf), "%s", request);
  738. ck_assert(client_conn != NULL);
  739. ri = mg_get_request_info(client_conn);
  740. ck_assert(ri != NULL);
  741. ck_assert_str_eq(ri->uri, "200");
  742. i = mg_read(client_conn, buf, sizeof(buf));
  743. ck_assert_int_eq(i, (int)strlen(expected));
  744. buf[i] = 0;
  745. ck_assert_str_eq(buf, expected);
  746. mg_close_connection(client_conn);
  747. /* Get data from callback using http://127.0.0.1 */
  748. client_conn = mg_download(
  749. "127.0.0.1", ipv4_port, 0, ebuf, sizeof(ebuf), "%s", request);
  750. ck_assert(client_conn != NULL);
  751. ri = mg_get_request_info(client_conn);
  752. ck_assert(ri != NULL);
  753. ck_assert_str_eq(ri->uri, "200");
  754. i = mg_read(client_conn, buf, sizeof(buf));
  755. if ((i >= 0) && ((size_t)i < sizeof(buf))) {
  756. buf[i] = 0;
  757. } else {
  758. ck_abort_msg(
  759. "ERROR: test_request_handlers: read returned %i (>=0, <%i)",
  760. (int)i,
  761. (int)sizeof(buf));
  762. }
  763. ck_assert((int)i < (int)sizeof(buf));
  764. ck_assert(i > 0);
  765. ck_assert_int_eq(i, (int)strlen(expected));
  766. buf[i] = 0;
  767. ck_assert_str_eq(buf, expected);
  768. mg_close_connection(client_conn);
  769. #if defined(USE_IPV6)
  770. /* Get data from callback using http://[::1] */
  771. client_conn =
  772. mg_download("[::1]", ipv6_port, 0, ebuf, sizeof(ebuf), "%s", request);
  773. ck_assert(client_conn != NULL);
  774. ri = mg_get_request_info(client_conn);
  775. ck_assert(ri != NULL);
  776. ck_assert_str_eq(ri->uri, "200");
  777. i = mg_read(client_conn, buf, sizeof(buf));
  778. ck_assert_int_eq(i, (int)strlen(expected));
  779. buf[i] = 0;
  780. ck_assert_str_eq(buf, expected);
  781. mg_close_connection(client_conn);
  782. #endif
  783. #if !defined(NO_SSL)
  784. /* Get data from callback using https://127.0.0.1 */
  785. client_conn = mg_download(
  786. "127.0.0.1", ipv4s_port, 1, ebuf, sizeof(ebuf), "%s", request);
  787. ck_assert(client_conn != NULL);
  788. ri = mg_get_request_info(client_conn);
  789. ck_assert(ri != NULL);
  790. ck_assert_str_eq(ri->uri, "200");
  791. i = mg_read(client_conn, buf, sizeof(buf));
  792. ck_assert_int_eq(i, (int)strlen(expected));
  793. buf[i] = 0;
  794. ck_assert_str_eq(buf, expected);
  795. mg_close_connection(client_conn);
  796. /* Get redirect from callback using http://127.0.0.1 */
  797. client_conn = mg_download(
  798. "127.0.0.1", ipv4r_port, 0, ebuf, sizeof(ebuf), "%s", request);
  799. ck_assert(client_conn != NULL);
  800. ri = mg_get_request_info(client_conn);
  801. ck_assert(ri != NULL);
  802. ck_assert_str_eq(ri->uri, "302");
  803. i = mg_read(client_conn, buf, sizeof(buf));
  804. ck_assert_int_eq(i, -1);
  805. mg_close_connection(client_conn);
  806. #endif
  807. #if defined(USE_IPV6) && !defined(NO_SSL)
  808. /* Get data from callback using https://[::1] */
  809. client_conn =
  810. mg_download("[::1]", ipv6s_port, 1, ebuf, sizeof(ebuf), "%s", request);
  811. ck_assert(client_conn != NULL);
  812. ri = mg_get_request_info(client_conn);
  813. ck_assert(ri != NULL);
  814. ck_assert_str_eq(ri->uri, "200");
  815. i = mg_read(client_conn, buf, sizeof(buf));
  816. ck_assert_int_eq(i, (int)strlen(expected));
  817. buf[i] = 0;
  818. ck_assert_str_eq(buf, expected);
  819. mg_close_connection(client_conn);
  820. /* Get redirect from callback using http://127.0.0.1 */
  821. client_conn =
  822. mg_download("[::1]", ipv6r_port, 0, ebuf, sizeof(ebuf), "%s", request);
  823. ck_assert(client_conn != NULL);
  824. ri = mg_get_request_info(client_conn);
  825. ck_assert(ri != NULL);
  826. ck_assert_str_eq(ri->uri, "302");
  827. i = mg_read(client_conn, buf, sizeof(buf));
  828. ck_assert_int_eq(i, -1);
  829. mg_close_connection(client_conn);
  830. #endif
  831. /* It seems to be impossible to find out what the actual working
  832. * directory of the CI test environment is. Before breaking another
  833. * dozen of builds by trying blindly with different paths, just
  834. * create the file here */
  835. #ifdef _WIN32
  836. f = fopen("test.txt", "wb");
  837. #else
  838. f = fopen("test.txt", "w");
  839. #endif
  840. plain_file_content = "simple text file\n";
  841. fwrite(plain_file_content, 17, 1, f);
  842. fclose(f);
  843. #ifdef _WIN32
  844. f = fopen("test_gz.txt.gz", "wb");
  845. #else
  846. f = fopen("test_gz.txt.gz", "w");
  847. #endif
  848. encoded_file_content = "\x1f\x8b\x08\x08\xf8\x9d\xcb\x55\x00\x00"
  849. "test_gz.txt"
  850. "\x00\x01\x11\x00\xee\xff"
  851. "zipped text file"
  852. "\x0a\x34\x5f\xcc\x49\x11\x00\x00\x00";
  853. fwrite(encoded_file_content, 1, 52, f);
  854. fclose(f);
  855. #ifdef _WIN32
  856. f = fopen("test.cgi", "wb");
  857. cgi_script_content = "#!test.cgi.cmd\r\n";
  858. fwrite(cgi_script_content, strlen(cgi_script_content), 1, f);
  859. fclose(f);
  860. f = fopen("test.cgi.cmd", "w");
  861. cgi_script_content = "@echo off\r\n"
  862. "echo Connection: close\r\n"
  863. "echo Content-Type: text/plain\r\n"
  864. "echo.\r\n"
  865. "echo CGI test\r\n"
  866. "\r\n";
  867. fwrite(cgi_script_content, strlen(cgi_script_content), 1, f);
  868. fclose(f);
  869. #else
  870. f = fopen("test.cgi", "w");
  871. cgi_script_content = "#!/bin/sh\n\n"
  872. "printf \"Connection: close\\r\\n\"\n"
  873. "printf \"Content-Type: text/plain\\r\\n\"\n"
  874. "printf \"\\r\\n\"\n"
  875. "printf \"CGI test\\r\\n\"\n"
  876. "\n";
  877. fwrite(cgi_script_content, strlen(cgi_script_content), 1, f);
  878. fclose(f);
  879. system("chmod a+x test.cgi");
  880. #endif
  881. expected_cgi_result = "CGI test";
  882. /* Get static data */
  883. client_conn = mg_download("localhost",
  884. ipv4_port,
  885. 0,
  886. ebuf,
  887. sizeof(ebuf),
  888. "%s",
  889. "GET /test.txt HTTP/1.0\r\n\r\n");
  890. ck_assert(client_conn != NULL);
  891. ri = mg_get_request_info(client_conn);
  892. ck_assert(ri != NULL);
  893. #if defined(NO_FILES)
  894. ck_assert_str_eq(ri->uri, "404");
  895. #else
  896. ck_assert_str_eq(ri->uri, "200");
  897. i = mg_read(client_conn, buf, sizeof(buf));
  898. ck_assert_int_eq(i, 17);
  899. if ((i >= 0) && (i < (int)sizeof(buf))) {
  900. buf[i] = 0;
  901. }
  902. ck_assert_str_eq(buf, plain_file_content);
  903. #endif
  904. mg_close_connection(client_conn);
  905. /* Test with CGI test executable */
  906. #if defined(_WIN32)
  907. sprintf(cmd_buf, "copy %s\\cgi_test.cgi cgi_test.exe", locate_test_exes());
  908. #else
  909. sprintf(cmd_buf, "cp %s/cgi_test.cgi cgi_test.cgi", locate_test_exes());
  910. #endif
  911. system(cmd_buf);
  912. #if !defined(NO_CGI) && !defined(NO_FILES) && !defined(_WIN32)
  913. /* TODO: add test for windows, check with POST */
  914. client_conn = mg_download(
  915. "localhost",
  916. ipv4_port,
  917. 0,
  918. ebuf,
  919. sizeof(ebuf),
  920. "%s",
  921. "POST /cgi_test.cgi HTTP/1.0\r\nContent-Length: 3\r\n\r\nABC");
  922. ck_assert(client_conn != NULL);
  923. ri = mg_get_request_info(client_conn);
  924. ck_assert(ri != NULL);
  925. ck_assert_str_eq(ri->uri, "200");
  926. mg_close_connection(client_conn);
  927. #endif
  928. /* Get zipped static data - will not work if Accept-Encoding is not set */
  929. client_conn = mg_download("localhost",
  930. ipv4_port,
  931. 0,
  932. ebuf,
  933. sizeof(ebuf),
  934. "%s",
  935. "GET /test_gz.txt HTTP/1.0\r\n\r\n");
  936. ck_assert(client_conn != NULL);
  937. ri = mg_get_request_info(client_conn);
  938. ck_assert(ri != NULL);
  939. ck_assert_str_eq(ri->uri, "404");
  940. mg_close_connection(client_conn);
  941. /* Get zipped static data - with Accept-Encoding */
  942. client_conn = mg_download(
  943. "localhost",
  944. ipv4_port,
  945. 0,
  946. ebuf,
  947. sizeof(ebuf),
  948. "%s",
  949. "GET /test_gz.txt HTTP/1.0\r\nAccept-Encoding: gzip\r\n\r\n");
  950. ck_assert(client_conn != NULL);
  951. ri = mg_get_request_info(client_conn);
  952. ck_assert(ri != NULL);
  953. #if defined(NO_FILES)
  954. ck_assert_str_eq(ri->uri, "404");
  955. #else
  956. ck_assert_str_eq(ri->uri, "200");
  957. i = mg_read(client_conn, buf, sizeof(buf));
  958. ck_assert_int_eq(i, 52);
  959. if ((i >= 0) && (i < (int)sizeof(buf))) {
  960. buf[i] = 0;
  961. }
  962. ck_assert_int_eq(ri->content_length, 52);
  963. ck_assert_str_eq(buf, encoded_file_content);
  964. #endif
  965. mg_close_connection(client_conn);
  966. /* Get CGI generated data */
  967. #if !defined(NO_CGI)
  968. client_conn = mg_download("localhost",
  969. ipv4_port,
  970. 0,
  971. ebuf,
  972. sizeof(ebuf),
  973. "%s",
  974. "GET /test.cgi HTTP/1.0\r\n\r\n");
  975. ck_assert(client_conn != NULL);
  976. ri = mg_get_request_info(client_conn);
  977. ck_assert(ri != NULL);
  978. #if defined(NO_FILES)
  979. ck_assert_str_eq(ri->uri, "404");
  980. (void)expected_cgi_result;
  981. (void)cgi_script_content;
  982. #else
  983. i = mg_read(client_conn, buf, sizeof(buf));
  984. if ((i >= 0) && (i < (int)sizeof(buf))) {
  985. while ((i > 0) && ((buf[i - 1] == '\r') || (buf[i - 1] == '\n'))) {
  986. i--;
  987. }
  988. buf[i] = 0;
  989. }
  990. /* ck_assert_int_eq(i, (int)strlen(expected_cgi_result)); */
  991. ck_assert_str_eq(buf, expected_cgi_result);
  992. ck_assert_str_eq(ri->uri, "200");
  993. mg_close_connection(client_conn);
  994. #endif
  995. #else
  996. (void)expected_cgi_result;
  997. (void)cgi_script_content;
  998. #endif
  999. /* Get directory listing */
  1000. client_conn = mg_download("localhost",
  1001. ipv4_port,
  1002. 0,
  1003. ebuf,
  1004. sizeof(ebuf),
  1005. "%s",
  1006. "GET / HTTP/1.0\r\n\r\n");
  1007. ck_assert(client_conn != NULL);
  1008. ri = mg_get_request_info(client_conn);
  1009. ck_assert(ri != NULL);
  1010. #if defined(NO_FILES)
  1011. ck_assert_str_eq(ri->uri, "404");
  1012. #else
  1013. ck_assert_str_eq(ri->uri, "200");
  1014. i = mg_read(client_conn, buf, sizeof(buf));
  1015. ck_assert(i > 6);
  1016. buf[6] = 0;
  1017. ck_assert_str_eq(buf, "<html>");
  1018. #endif
  1019. mg_close_connection(client_conn);
  1020. /* POST to static file (will not work) */
  1021. client_conn = mg_download("localhost",
  1022. ipv4_port,
  1023. 0,
  1024. ebuf,
  1025. sizeof(ebuf),
  1026. "%s",
  1027. "POST /test.txt HTTP/1.0\r\n\r\n");
  1028. ck_assert(client_conn != NULL);
  1029. ri = mg_get_request_info(client_conn);
  1030. ck_assert(ri != NULL);
  1031. #if defined(NO_FILES)
  1032. ck_assert_str_eq(ri->uri, "404");
  1033. #else
  1034. ck_assert_str_eq(ri->uri, "405");
  1035. i = mg_read(client_conn, buf, sizeof(buf));
  1036. ck_assert(i >= 29);
  1037. buf[29] = 0;
  1038. ck_assert_str_eq(buf, "Error 405: Method Not Allowed");
  1039. #endif
  1040. mg_close_connection(client_conn);
  1041. /* PUT to static file (will not work) */
  1042. client_conn = mg_download("localhost",
  1043. ipv4_port,
  1044. 0,
  1045. ebuf,
  1046. sizeof(ebuf),
  1047. "%s",
  1048. "PUT /test.txt HTTP/1.0\r\n\r\n");
  1049. ck_assert(client_conn != NULL);
  1050. ri = mg_get_request_info(client_conn);
  1051. ck_assert(ri != NULL);
  1052. #if defined(NO_FILES)
  1053. ck_assert_str_eq(ri->uri, "405"); /* method not allowed */
  1054. #else
  1055. ck_assert_str_eq(ri->uri, "401"); /* not authorized */
  1056. #endif
  1057. mg_close_connection(client_conn);
  1058. /* Websocket test */
  1059. #ifdef USE_WEBSOCKET
  1060. /* Then connect a first client */
  1061. ws_client1_conn =
  1062. mg_connect_websocket_client("localhost",
  1063. ipv4_port,
  1064. 0,
  1065. ebuf,
  1066. sizeof(ebuf),
  1067. "/websocket",
  1068. NULL,
  1069. websocket_client_data_handler,
  1070. websocket_client_close_handler,
  1071. &ws_client1_data);
  1072. ck_assert(ws_client1_conn != NULL);
  1073. wait_not_null(
  1074. &(ws_client1_data.data)); /* Wait for the websocket welcome message */
  1075. ck_assert_int_eq(ws_client1_data.closed, 0);
  1076. ck_assert_int_eq(ws_client2_data.closed, 0);
  1077. ck_assert_int_eq(ws_client3_data.closed, 0);
  1078. ck_assert(ws_client2_data.data == NULL);
  1079. ck_assert_uint_eq(ws_client2_data.len, 0);
  1080. ck_assert(ws_client1_data.data != NULL);
  1081. ck_assert_uint_eq(ws_client1_data.len, websocket_welcome_msg_len);
  1082. ck_assert(!memcmp(ws_client1_data.data,
  1083. websocket_welcome_msg,
  1084. websocket_welcome_msg_len));
  1085. free(ws_client1_data.data);
  1086. ws_client1_data.data = NULL;
  1087. ws_client1_data.len = 0;
  1088. mg_websocket_client_write(ws_client1_conn,
  1089. WEBSOCKET_OPCODE_TEXT,
  1090. "data1",
  1091. 5);
  1092. wait_not_null(
  1093. &(ws_client1_data
  1094. .data)); /* Wait for the websocket acknowledge message */
  1095. ck_assert_int_eq(ws_client1_data.closed, 0);
  1096. ck_assert_int_eq(ws_client2_data.closed, 0);
  1097. ck_assert(ws_client2_data.data == NULL);
  1098. ck_assert_uint_eq(ws_client2_data.len, 0);
  1099. ck_assert(ws_client1_data.data != NULL);
  1100. ck_assert_uint_eq(ws_client1_data.len, 3);
  1101. ck_assert(!memcmp(ws_client1_data.data, "ok1", 3));
  1102. free(ws_client1_data.data);
  1103. ws_client1_data.data = NULL;
  1104. ws_client1_data.len = 0;
  1105. /* Now connect a second client */
  1106. #ifdef USE_IPV6
  1107. ws_client2_conn =
  1108. mg_connect_websocket_client("[::1]",
  1109. ipv6_port,
  1110. 0,
  1111. ebuf,
  1112. sizeof(ebuf),
  1113. "/websocket",
  1114. NULL,
  1115. websocket_client_data_handler,
  1116. websocket_client_close_handler,
  1117. &ws_client2_data);
  1118. #else
  1119. ws_client2_conn =
  1120. mg_connect_websocket_client("127.0.0.1",
  1121. ipv4_port,
  1122. 0,
  1123. ebuf,
  1124. sizeof(ebuf),
  1125. "/websocket",
  1126. NULL,
  1127. websocket_client_data_handler,
  1128. websocket_client_close_handler,
  1129. &ws_client2_data);
  1130. #endif
  1131. ck_assert(ws_client2_conn != NULL);
  1132. wait_not_null(
  1133. &(ws_client2_data.data)); /* Wait for the websocket welcome message */
  1134. ck_assert(ws_client1_data.closed == 0);
  1135. ck_assert(ws_client2_data.closed == 0);
  1136. ck_assert(ws_client1_data.data == NULL);
  1137. ck_assert(ws_client1_data.len == 0);
  1138. ck_assert(ws_client2_data.data != NULL);
  1139. ck_assert(ws_client2_data.len == websocket_welcome_msg_len);
  1140. ck_assert(!memcmp(ws_client2_data.data,
  1141. websocket_welcome_msg,
  1142. websocket_welcome_msg_len));
  1143. free(ws_client2_data.data);
  1144. ws_client2_data.data = NULL;
  1145. ws_client2_data.len = 0;
  1146. mg_websocket_client_write(ws_client1_conn,
  1147. WEBSOCKET_OPCODE_TEXT,
  1148. "data2",
  1149. 5);
  1150. wait_not_null(
  1151. &(ws_client1_data
  1152. .data)); /* Wait for the websocket acknowledge message */
  1153. ck_assert(ws_client1_data.closed == 0);
  1154. ck_assert(ws_client2_data.closed == 0);
  1155. ck_assert(ws_client2_data.data == NULL);
  1156. ck_assert(ws_client2_data.len == 0);
  1157. ck_assert(ws_client1_data.data != NULL);
  1158. ck_assert(ws_client1_data.len == 4);
  1159. ck_assert(!memcmp(ws_client1_data.data, "ok 2", 4));
  1160. free(ws_client1_data.data);
  1161. ws_client1_data.data = NULL;
  1162. ws_client1_data.len = 0;
  1163. mg_websocket_client_write(ws_client1_conn, WEBSOCKET_OPCODE_TEXT, "bye", 3);
  1164. wait_not_null(
  1165. &(ws_client1_data.data)); /* Wait for the websocket goodbye message */
  1166. ck_assert(ws_client1_data.closed == 0);
  1167. ck_assert(ws_client2_data.closed == 0);
  1168. ck_assert(ws_client2_data.data == NULL);
  1169. ck_assert(ws_client2_data.len == 0);
  1170. ck_assert(ws_client1_data.data != NULL);
  1171. ck_assert(ws_client1_data.len == websocket_goodbye_msg_len);
  1172. ck_assert(!memcmp(ws_client1_data.data,
  1173. websocket_goodbye_msg,
  1174. websocket_goodbye_msg_len));
  1175. free(ws_client1_data.data);
  1176. ws_client1_data.data = NULL;
  1177. ws_client1_data.len = 0;
  1178. mg_close_connection(ws_client1_conn);
  1179. test_sleep(3); /* Won't get any message */
  1180. ck_assert(ws_client1_data.closed == 1);
  1181. ck_assert(ws_client2_data.closed == 0);
  1182. ck_assert(ws_client1_data.data == NULL);
  1183. ck_assert(ws_client1_data.len == 0);
  1184. ck_assert(ws_client2_data.data == NULL);
  1185. ck_assert(ws_client2_data.len == 0);
  1186. mg_websocket_client_write(ws_client2_conn, WEBSOCKET_OPCODE_TEXT, "bye", 3);
  1187. wait_not_null(
  1188. &(ws_client2_data.data)); /* Wait for the websocket goodbye message */
  1189. ck_assert(ws_client1_data.closed == 1);
  1190. ck_assert(ws_client2_data.closed == 0);
  1191. ck_assert(ws_client1_data.data == NULL);
  1192. ck_assert(ws_client1_data.len == 0);
  1193. ck_assert(ws_client2_data.data != NULL);
  1194. ck_assert(ws_client2_data.len == websocket_goodbye_msg_len);
  1195. ck_assert(!memcmp(ws_client2_data.data,
  1196. websocket_goodbye_msg,
  1197. websocket_goodbye_msg_len));
  1198. free(ws_client2_data.data);
  1199. ws_client2_data.data = NULL;
  1200. ws_client2_data.len = 0;
  1201. mg_close_connection(ws_client2_conn);
  1202. test_sleep(3); /* Won't get any message */
  1203. ck_assert(ws_client1_data.closed == 1);
  1204. ck_assert(ws_client2_data.closed == 1);
  1205. ck_assert(ws_client1_data.data == NULL);
  1206. ck_assert(ws_client1_data.len == 0);
  1207. ck_assert(ws_client2_data.data == NULL);
  1208. ck_assert(ws_client2_data.len == 0);
  1209. /* Connect client 3 */
  1210. ws_client3_conn =
  1211. mg_connect_websocket_client("localhost",
  1212. #if defined(NO_SSL)
  1213. ipv4_port,
  1214. 0,
  1215. #else
  1216. ipv4s_port,
  1217. 1,
  1218. #endif
  1219. ebuf,
  1220. sizeof(ebuf),
  1221. "/websocket",
  1222. NULL,
  1223. websocket_client_data_handler,
  1224. websocket_client_close_handler,
  1225. &ws_client3_data);
  1226. ck_assert(ws_client3_conn != NULL);
  1227. wait_not_null(
  1228. &(ws_client3_data.data)); /* Wait for the websocket welcome message */
  1229. ck_assert(ws_client1_data.closed == 1);
  1230. ck_assert(ws_client2_data.closed == 1);
  1231. ck_assert(ws_client3_data.closed == 0);
  1232. ck_assert(ws_client1_data.data == NULL);
  1233. ck_assert(ws_client1_data.len == 0);
  1234. ck_assert(ws_client2_data.data == NULL);
  1235. ck_assert(ws_client2_data.len == 0);
  1236. ck_assert(ws_client3_data.data != NULL);
  1237. ck_assert(ws_client3_data.len == websocket_welcome_msg_len);
  1238. ck_assert(!memcmp(ws_client3_data.data,
  1239. websocket_welcome_msg,
  1240. websocket_welcome_msg_len));
  1241. free(ws_client3_data.data);
  1242. ws_client3_data.data = NULL;
  1243. ws_client3_data.len = 0;
  1244. #endif
  1245. /* Close the server */
  1246. g_ctx = NULL;
  1247. mg_stop(ctx);
  1248. mark_point();
  1249. #ifdef USE_WEBSOCKET
  1250. for (i = 0; i < 100; i++) {
  1251. test_sleep(1);
  1252. if (ws_client3_data.closed != 0) {
  1253. mark_point();
  1254. break;
  1255. }
  1256. }
  1257. ck_assert_int_eq(ws_client3_data.closed, 1);
  1258. #endif
  1259. }
  1260. END_TEST
  1261. static int
  1262. field_found(const char *key,
  1263. const char *filename,
  1264. char *path,
  1265. size_t pathlen,
  1266. void *user_data)
  1267. {
  1268. (void)key;
  1269. (void)filename;
  1270. (void)path;
  1271. (void)pathlen;
  1272. (void)user_data;
  1273. return FORM_FIELD_STORAGE_GET;
  1274. }
  1275. static int g_field_step;
  1276. static int
  1277. field_get(const char *key, const char *value, size_t valuelen, void *user_data)
  1278. {
  1279. (void)key;
  1280. (void)value;
  1281. (void)valuelen;
  1282. (void)user_data;
  1283. ck_assert(user_data == (void *)0x12345);
  1284. ++g_field_step;
  1285. switch (g_field_step) {
  1286. case 1:
  1287. ck_assert_str_eq(key, "textin");
  1288. ck_assert_uint_eq(valuelen, 4);
  1289. ck_assert_str_eq(value, "text");
  1290. break;
  1291. case 2:
  1292. ck_assert_str_eq(key, "passwordin");
  1293. ck_assert_uint_eq(valuelen, 0);
  1294. ck_assert_str_eq(value, "");
  1295. break;
  1296. case 3:
  1297. ck_assert_str_eq(key, "radio1");
  1298. ck_assert_uint_eq(valuelen, 4);
  1299. ck_assert_str_eq(value, "val1");
  1300. break;
  1301. case 4:
  1302. ck_assert_str_eq(key, "radio2");
  1303. ck_assert_uint_eq(valuelen, 4);
  1304. ck_assert_str_eq(value, "val1");
  1305. break;
  1306. case 5:
  1307. ck_assert_str_eq(key, "check1");
  1308. ck_assert_uint_eq(valuelen, 4);
  1309. ck_assert_str_eq(value, "val1");
  1310. break;
  1311. case 6:
  1312. ck_assert_str_eq(key, "numberin");
  1313. ck_assert_uint_eq(valuelen, 1);
  1314. ck_assert_str_eq(value, "1");
  1315. break;
  1316. case 7:
  1317. ck_assert_str_eq(key, "datein");
  1318. ck_assert_uint_eq(valuelen, 8);
  1319. ck_assert_str_eq(value, "1.1.2016");
  1320. break;
  1321. case 8:
  1322. ck_assert_str_eq(key, "colorin");
  1323. ck_assert_uint_eq(valuelen, 7);
  1324. ck_assert_str_eq(value, "#80ff00");
  1325. break;
  1326. case 9:
  1327. ck_assert_str_eq(key, "rangein");
  1328. ck_assert_uint_eq(valuelen, 1);
  1329. ck_assert_str_eq(value, "3");
  1330. break;
  1331. case 10:
  1332. ck_assert_str_eq(key, "monthin");
  1333. ck_assert_uint_eq(valuelen, 0);
  1334. ck_assert_str_eq(value, "");
  1335. break;
  1336. case 11:
  1337. ck_assert_str_eq(key, "weekin");
  1338. ck_assert_uint_eq(valuelen, 0);
  1339. ck_assert_str_eq(value, "");
  1340. break;
  1341. case 12:
  1342. ck_assert_str_eq(key, "timein");
  1343. ck_assert_uint_eq(valuelen, 0);
  1344. ck_assert_str_eq(value, "");
  1345. break;
  1346. case 13:
  1347. ck_assert_str_eq(key, "datetimen");
  1348. ck_assert_uint_eq(valuelen, 0);
  1349. ck_assert_str_eq(value, "");
  1350. break;
  1351. case 14:
  1352. ck_assert_str_eq(key, "datetimelocalin");
  1353. ck_assert_uint_eq(valuelen, 0);
  1354. ck_assert_str_eq(value, "");
  1355. break;
  1356. case 15:
  1357. ck_assert_str_eq(key, "emailin");
  1358. ck_assert_uint_eq(valuelen, 0);
  1359. ck_assert_str_eq(value, "");
  1360. break;
  1361. case 16:
  1362. ck_assert_str_eq(key, "searchin");
  1363. ck_assert_uint_eq(valuelen, 0);
  1364. ck_assert_str_eq(value, "");
  1365. break;
  1366. case 17:
  1367. ck_assert_str_eq(key, "telin");
  1368. ck_assert_uint_eq(valuelen, 0);
  1369. ck_assert_str_eq(value, "");
  1370. break;
  1371. case 18:
  1372. ck_assert_str_eq(key, "urlin");
  1373. ck_assert_uint_eq(valuelen, 0);
  1374. ck_assert_str_eq(value, "");
  1375. break;
  1376. case 19:
  1377. ck_assert_str_eq(key, "filein");
  1378. ck_assert_uint_eq(valuelen, 0);
  1379. ck_assert_str_eq(value, "");
  1380. break;
  1381. case 20:
  1382. ck_assert_str_eq(key, "filesin");
  1383. ck_assert_uint_eq(valuelen, 0);
  1384. ck_assert_str_eq(value, "");
  1385. break;
  1386. case 21:
  1387. ck_assert_str_eq(key, "selectin");
  1388. ck_assert_uint_eq(valuelen, 4);
  1389. ck_assert_str_eq(value, "opt1");
  1390. break;
  1391. case 22:
  1392. ck_assert_str_eq(key, "message");
  1393. ck_assert_uint_eq(valuelen, 23);
  1394. ck_assert_str_eq(value, "Text area default text.");
  1395. break;
  1396. default:
  1397. ck_abort_msg("field_get called with g_field_step == %i", (int)g_field_step);
  1398. }
  1399. return 0;
  1400. }
  1401. static int
  1402. FormHandler(struct mg_connection *conn, void *cbdata)
  1403. {
  1404. const struct mg_request_info *req_info = mg_get_request_info(conn);
  1405. int ret;
  1406. struct mg_form_data_handler fdh = {field_found, field_get, NULL, NULL};
  1407. (void)cbdata;
  1408. ck_assert(req_info != NULL);
  1409. mg_printf(conn, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n");
  1410. fdh.user_data = (void *)0x12345;
  1411. /* Call the form handler */
  1412. g_field_step = 0;
  1413. ret = mg_handle_form_request(conn, &fdh);
  1414. ck_assert_int_eq(ret, 22);
  1415. ck_assert_int_eq(g_field_step, 22);
  1416. mg_printf(conn, "%i\r\n", ret);
  1417. return 1;
  1418. }
  1419. START_TEST(test_handle_form)
  1420. {
  1421. struct mg_context *ctx;
  1422. struct mg_connection *client_conn;
  1423. const struct mg_request_info *ri;
  1424. const char *OPTIONS[8];
  1425. const char *opt;
  1426. int opt_idx = 0;
  1427. char ebuf[100];
  1428. memset((void *)OPTIONS, 0, sizeof(OPTIONS));
  1429. OPTIONS[opt_idx++] = "listening_ports";
  1430. OPTIONS[opt_idx++] = "8884";
  1431. ck_assert_int_le(opt_idx, (int)(sizeof(OPTIONS) / sizeof(OPTIONS[0])));
  1432. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
  1433. ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);
  1434. mark_point();
  1435. ctx = mg_start(NULL, &g_ctx, OPTIONS);
  1436. ck_assert(ctx != NULL);
  1437. g_ctx = ctx;
  1438. opt = mg_get_option(ctx, "listening_ports");
  1439. ck_assert_str_eq(opt, "8884");
  1440. mg_set_request_handler(ctx, "/handle_form", FormHandler, (void *)0);
  1441. test_sleep(1);
  1442. /* Handle form: "GET" */
  1443. client_conn = mg_download("localhost",
  1444. 8884,
  1445. 0,
  1446. ebuf,
  1447. sizeof(ebuf),
  1448. "%s",
  1449. "GET /handle_form"
  1450. "?textin=text&passwordin=&radio1=val1"
  1451. "&radio2=val1&check1=val1&numberin=1"
  1452. "&datein=1.1.2016&colorin=%2380ff00"
  1453. "&rangein=3&monthin=&weekin=&timein="
  1454. "&datetimen=&datetimelocalin=&emailin="
  1455. "&searchin=&telin=&urlin=&filein="
  1456. "&filesin=&selectin=opt1"
  1457. "&message=Text+area+default+text. "
  1458. "HTTP/1.0\r\n"
  1459. "Host: localhost:8884\r\n"
  1460. "Connection: close\r\n\r\n");
  1461. ck_assert(client_conn != NULL);
  1462. test_sleep(1);
  1463. ri = mg_get_request_info(client_conn);
  1464. ck_assert(ri != NULL);
  1465. ck_assert_str_eq(ri->uri, "200");
  1466. mg_close_connection(client_conn);
  1467. /* Handle form: "POST x-www-form-urlencoded" */
  1468. client_conn =
  1469. mg_download("localhost",
  1470. 8884,
  1471. 0,
  1472. ebuf,
  1473. sizeof(ebuf),
  1474. "%s",
  1475. "POST /handle_form HTTP/1.1\r\n"
  1476. "Host: localhost:8884\r\n"
  1477. "Connection: close\r\n"
  1478. "Content-Type: application/x-www-form-urlencoded\r\n"
  1479. "Content-Length: 263\r\n"
  1480. "\r\n"
  1481. "textin=text&passwordin=&radio1=val1&radio2=val1"
  1482. "&check1=val1&numberin=1&datein=1.1.2016"
  1483. "&colorin=%2380ff00&rangein=3&monthin=&weekin="
  1484. "&timein=&datetimen=&datetimelocalin=&emailin="
  1485. "&searchin=&telin=&urlin=&filein=&filesin="
  1486. "&selectin=opt1&message=Text+area+default+text.");
  1487. ck_assert(client_conn != NULL);
  1488. test_sleep(1);
  1489. ri = mg_get_request_info(client_conn);
  1490. ck_assert(ri != NULL);
  1491. ck_assert_str_eq(ri->uri, "200");
  1492. mg_close_connection(client_conn);
  1493. /* Handle form: "POST multipart/form-data" */
  1494. client_conn = mg_download(
  1495. "localhost",
  1496. 8884,
  1497. 0,
  1498. ebuf,
  1499. sizeof(ebuf),
  1500. "%s",
  1501. "POST /handle_form HTTP/1.1\r\n"
  1502. "Host: localhost:8884\r\n"
  1503. "Connection: close\r\n"
  1504. "Content-Type: multipart/form-data; "
  1505. "boundary=multipart-form-data-boundary--see-RFC-2388\r\n"
  1506. "Content-Length: 2374\r\n"
  1507. "\r\n"
  1508. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1509. "Content-Disposition: form-data; name=\"textin\"\r\n"
  1510. "\r\n"
  1511. "text\r\n"
  1512. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1513. "Content-Disposition: form-data; name=\"passwordin\"\r\n"
  1514. "\r\n"
  1515. "\r\n"
  1516. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1517. "Content-Disposition: form-data; name=\"radio1\"\r\n"
  1518. "\r\n"
  1519. "val1\r\n"
  1520. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1521. "Content-Disposition: form-data; name=\"radio2\"\r\n"
  1522. "\r\n"
  1523. "val1\r\n"
  1524. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1525. "Content-Disposition: form-data; name=\"check1\"\r\n"
  1526. "\r\n"
  1527. "val1\r\n"
  1528. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1529. "Content-Disposition: form-data; name=\"numberin\"\r\n"
  1530. "\r\n"
  1531. "1\r\n"
  1532. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1533. "Content-Disposition: form-data; name=\"datein\"\r\n"
  1534. "\r\n"
  1535. "1.1.2016\r\n"
  1536. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1537. "Content-Disposition: form-data; name=\"colorin\"\r\n"
  1538. "\r\n"
  1539. "#80ff00\r\n"
  1540. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1541. "Content-Disposition: form-data; name=\"rangein\"\r\n"
  1542. "\r\n"
  1543. "3\r\n"
  1544. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1545. "Content-Disposition: form-data; name=\"monthin\"\r\n"
  1546. "\r\n"
  1547. "\r\n"
  1548. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1549. "Content-Disposition: form-data; name=\"weekin\"\r\n"
  1550. "\r\n"
  1551. "\r\n"
  1552. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1553. "Content-Disposition: form-data; name=\"timein\"\r\n"
  1554. "\r\n"
  1555. "\r\n"
  1556. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1557. "Content-Disposition: form-data; name=\"datetimen\"\r\n"
  1558. "\r\n"
  1559. "\r\n"
  1560. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1561. "Content-Disposition: form-data; name=\"datetimelocalin\"\r\n"
  1562. "\r\n"
  1563. "\r\n"
  1564. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1565. "Content-Disposition: form-data; name=\"emailin\"\r\n"
  1566. "\r\n"
  1567. "\r\n"
  1568. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1569. "Content-Disposition: form-data; name=\"searchin\"\r\n"
  1570. "\r\n"
  1571. "\r\n"
  1572. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1573. "Content-Disposition: form-data; name=\"telin\"\r\n"
  1574. "\r\n"
  1575. "\r\n"
  1576. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1577. "Content-Disposition: form-data; name=\"urlin\"\r\n"
  1578. "\r\n"
  1579. "\r\n"
  1580. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1581. "Content-Disposition: form-data; name=\"filein\"; filename=\"\"\r\n"
  1582. "Content-Type: application/octet-stream\r\n"
  1583. "\r\n"
  1584. "\r\n"
  1585. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1586. "Content-Disposition: form-data; name=\"filesin\"; filename=\"\"\r\n"
  1587. "Content-Type: application/octet-stream\r\n"
  1588. "\r\n"
  1589. "\r\n"
  1590. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1591. "Content-Disposition: form-data; name=\"selectin\"\r\n"
  1592. "\r\n"
  1593. "opt1\r\n"
  1594. "--multipart-form-data-boundary--see-RFC-2388\r\n"
  1595. "Content-Disposition: form-data; name=\"message\"\r\n"
  1596. "\r\n"
  1597. "Text area default text.\r\n"
  1598. "--multipart-form-data-boundary--see-RFC-2388--\r\n");
  1599. ck_assert(client_conn != NULL);
  1600. test_sleep(1);
  1601. ri = mg_get_request_info(client_conn);
  1602. ck_assert(ri != NULL);
  1603. ck_assert_str_eq(ri->uri, "200");
  1604. mg_close_connection(client_conn);
  1605. /* Close the server */
  1606. g_ctx = NULL;
  1607. mg_stop(ctx);
  1608. mark_point();
  1609. }
  1610. END_TEST
  1611. Suite *
  1612. make_public_server_suite(void)
  1613. {
  1614. Suite *const suite = suite_create("PublicServer");
  1615. TCase *const tcase_checktestenv = tcase_create("Check test environment");
  1616. TCase *const tcase_startthreads = tcase_create("Start threads");
  1617. TCase *const tcase_startstophttp = tcase_create("Start Stop HTTP Server");
  1618. TCase *const tcase_startstophttps = tcase_create("Start Stop HTTPS Server");
  1619. TCase *const tcase_serverandclienttls = tcase_create("TLS Server Client");
  1620. TCase *const tcase_serverrequests = tcase_create("Server Requests");
  1621. TCase *const tcase_handle_form = tcase_create("Handle Form");
  1622. tcase_add_test(tcase_checktestenv, test_the_test_environment);
  1623. tcase_set_timeout(tcase_checktestenv, civetweb_min_test_timeout);
  1624. suite_add_tcase(suite, tcase_checktestenv);
  1625. tcase_add_test(tcase_startthreads, test_threading);
  1626. tcase_set_timeout(tcase_startthreads, civetweb_min_test_timeout);
  1627. suite_add_tcase(suite, tcase_startthreads);
  1628. tcase_add_test(tcase_startstophttp, test_mg_start_stop_http_server);
  1629. tcase_set_timeout(tcase_startstophttp, civetweb_min_test_timeout);
  1630. suite_add_tcase(suite, tcase_startstophttp);
  1631. tcase_add_test(tcase_startstophttps, test_mg_start_stop_https_server);
  1632. tcase_set_timeout(tcase_startstophttps, civetweb_min_test_timeout);
  1633. suite_add_tcase(suite, tcase_startstophttps);
  1634. tcase_add_test(tcase_serverandclienttls, test_mg_server_and_client_tls);
  1635. tcase_set_timeout(tcase_serverandclienttls, civetweb_min_test_timeout);
  1636. suite_add_tcase(suite, tcase_serverandclienttls);
  1637. tcase_add_test(tcase_serverrequests, test_request_handlers);
  1638. tcase_set_timeout(tcase_serverrequests, 120);
  1639. suite_add_tcase(suite, tcase_serverrequests);
  1640. tcase_add_test(tcase_handle_form, test_handle_form);
  1641. tcase_set_timeout(tcase_handle_form, 60);
  1642. suite_add_tcase(suite, tcase_handle_form);
  1643. return suite;
  1644. }
  1645. #ifdef REPLACE_CHECK_FOR_LOCAL_DEBUGGING
  1646. /* Used to debug test cases without using the check framework */
  1647. static int chk_ok = 0;
  1648. static int chk_failed = 0;
  1649. void
  1650. main(void)
  1651. {
  1652. /*
  1653. test_the_test_environment(0);
  1654. test_threading(0);
  1655. test_mg_start_stop_http_server(0);
  1656. test_mg_start_stop_https_server(0);
  1657. test_request_handlers(0);
  1658. test_mg_server_and_client_tls(0);
  1659. */
  1660. test_handle_form(0);
  1661. printf("\nok: %i\nfailed: %i\n\n", chk_ok, chk_failed);
  1662. }
  1663. void
  1664. _ck_assert_failed(const char *file, int line, const char *expr, ...)
  1665. {
  1666. va_list va;
  1667. va_start(va, expr);
  1668. fprintf(stderr, "Error: %s, line %i\n", file, line); /* breakpoint here ! */
  1669. vfprintf(stderr, expr, va);
  1670. fprintf(stderr, "\n\n");
  1671. va_end(va);
  1672. chk_failed++;
  1673. }
  1674. void
  1675. _ck_assert_msg(int cond, const char *file, int line, const char *expr, ...)
  1676. {
  1677. va_list va;
  1678. if (cond) {
  1679. chk_ok++;
  1680. return;
  1681. }
  1682. va_start(va, expr);
  1683. fprintf(stderr, "Error: %s, line %i\n", file, line); /* breakpoint here ! */
  1684. vfprintf(stderr, expr, va);
  1685. fprintf(stderr, "\n\n");
  1686. va_end(va);
  1687. chk_failed++;
  1688. }
  1689. void
  1690. _mark_point(const char *file, int line)
  1691. {
  1692. chk_ok++;
  1693. }
  1694. void
  1695. tcase_fn_start(const char *fname, const char *file, int line)
  1696. {
  1697. }
  1698. void suite_add_tcase(Suite *s, TCase *tc){};
  1699. void _tcase_add_test(TCase *tc,
  1700. TFun tf,
  1701. const char *fname,
  1702. int _signal,
  1703. int allowed_exit_value,
  1704. int start,
  1705. int end){};
  1706. TCase *
  1707. tcase_create(const char *name)
  1708. {
  1709. return NULL;
  1710. };
  1711. Suite *
  1712. suite_create(const char *name)
  1713. {
  1714. return NULL;
  1715. };
  1716. void tcase_set_timeout(TCase *tc, double timeout){};
  1717. #endif