http_client.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /* libanode: the Anode C reference implementation
  2. * Copyright (C) 2009-2010 Adam Ierymenko <[email protected]>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>. */
  16. #include <stdio.h>
  17. #include <netinet/in.h>
  18. #include <sys/socket.h>
  19. #include "http_client.h"
  20. #include "misc.h"
  21. #include "types.h"
  22. /* How much to increment read buffer at each capacity top? */
  23. #define ANODE_HTTP_CAPACITY_INCREMENT 4096
  24. static void AnodeHttpClient_close_and_fail(struct AnodeHttpClient *client)
  25. {
  26. if (client->impl.tcp_connection) {
  27. client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection);
  28. client->impl.tcp_connection = (AnodeTransportTcpConnection *)0;
  29. }
  30. client->response.data_length = 0;
  31. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED;
  32. if (client->handler)
  33. client->handler(client);
  34. }
  35. static void AnodeHttpClient_do_initiate_client(struct AnodeHttpClient *client)
  36. {
  37. const char *method = "";
  38. long l,i;
  39. switch(client->method) {
  40. case ANODE_HTTP_GET: method = "GET"; break;
  41. case ANODE_HTTP_HEAD: method = "HEAD"; break;
  42. case ANODE_HTTP_POST: method = "POST"; break;
  43. }
  44. client->impl.outbuf_len = snprintf((char *)client->impl.outbuf,sizeof(client->impl.outbuf),
  45. "%s %s%s%s HTTP/1.1\r\nHost: %s:%d\r\n%s",
  46. method,
  47. client->uri.path,
  48. ((client->uri.query[0]) ? "?" : ""),
  49. client->uri.query,
  50. client->uri.host,
  51. ((client->uri.port > 0) ? client->uri.port : 80),
  52. ((client->keepalive) ? "" : "Connection: close\r\n")
  53. );
  54. if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) {
  55. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE;
  56. AnodeHttpClient_close_and_fail(client);
  57. return;
  58. }
  59. if (client->method == ANODE_HTTP_POST) {
  60. if ((client->data)&&(client->data_length)) {
  61. client->impl.outbuf_len += snprintf((char *)client->impl.outbuf + client->impl.outbuf_len,sizeof(client->impl.outbuf) - client->impl.outbuf_len,
  62. "Content-Type: %s\r\n",
  63. (client->data_content_type ? client->data_content_type : "application/x-www-form-urlencoded")
  64. );
  65. if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) {
  66. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE;
  67. AnodeHttpClient_close_and_fail(client);
  68. return;
  69. }
  70. client->impl.outbuf_len += snprintf((char *)client->impl.outbuf + client->impl.outbuf_len,sizeof(client->impl.outbuf) - client->impl.outbuf_len,
  71. "Content-Length: %u\r\n",
  72. client->data_length
  73. );
  74. if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) {
  75. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE;
  76. AnodeHttpClient_close_and_fail(client);
  77. return;
  78. }
  79. } else {
  80. client->impl.outbuf_len += snprintf((char *)client->impl.outbuf + client->impl.outbuf_len,sizeof(client->impl.outbuf) - client->impl.outbuf_len,
  81. "Content-Length: 0\r\n"
  82. );
  83. if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) {
  84. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE;
  85. AnodeHttpClient_close_and_fail(client);
  86. return;
  87. }
  88. }
  89. }
  90. l = AnodeDictionary_write(&(client->headers),(char *)client->impl.outbuf + client->impl.outbuf_len,(long)(sizeof(client->impl.outbuf) - client->impl.outbuf_len - 2),"\r\n",": ");
  91. if (l < 0) {
  92. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE;
  93. AnodeHttpClient_close_and_fail(client);
  94. return;
  95. }
  96. client->impl.outbuf_len += (unsigned int)l;
  97. if (client->impl.outbuf_len >= (sizeof(client->impl.outbuf) - 2)) { /* sanity check */
  98. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_HEADERS_TOO_LARGE;
  99. AnodeHttpClient_close_and_fail(client);
  100. return;
  101. }
  102. client->impl.outbuf[client->impl.outbuf_len++] = '\r';
  103. client->impl.outbuf[client->impl.outbuf_len++] = '\n';
  104. if ((client->method == ANODE_HTTP_POST)&&(client->data)&&(client->data_length)) {
  105. i = sizeof(client->impl.outbuf) - client->impl.outbuf_len;
  106. if (i > client->data_length)
  107. i = client->data_length;
  108. Anode_memcpy((client->impl.outbuf + client->impl.outbuf_len),client->data,i);
  109. client->impl.request_data_ptr += i;
  110. client->impl.outbuf_len += i;
  111. }
  112. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_SEND;
  113. client->impl.transport_engine->tcp_start_writing(client->impl.transport_engine,client->impl.tcp_connection);
  114. }
  115. static void AnodeHttpClient_tcp_outgoing_connect_handler(
  116. AnodeTransportEngine *transport,
  117. AnodeTransportTcpConnection *connection,
  118. int error_code)
  119. {
  120. struct AnodeHttpClient *client;
  121. if (!(client = (struct AnodeHttpClient *)(connection->ptr)))
  122. return;
  123. if ((client->impl.phase == ANODE_HTTP_REQUEST_PHASE_CONNECT)&&(!client->impl.freed)) {
  124. if (error_code) {
  125. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_CONNECT_FAILED;
  126. AnodeHttpClient_close_and_fail(client);
  127. } else {
  128. client->impl.tcp_connection = connection;
  129. AnodeHttpClient_do_initiate_client(client);
  130. }
  131. } else transport->tcp_close(transport,connection);
  132. }
  133. static void AnodeHttpClient_tcp_connection_terminated_handler(
  134. AnodeTransportEngine *transport,
  135. AnodeTransportTcpConnection *connection,
  136. int error_code)
  137. {
  138. struct AnodeHttpClient *client;
  139. if (!(client = (struct AnodeHttpClient *)(connection->ptr)))
  140. return;
  141. if (client->impl.freed)
  142. return;
  143. client->response.data_length = 0;
  144. client->impl.tcp_connection = (AnodeTransportTcpConnection *)0;
  145. if ((client->impl.phase != ANODE_HTTP_REQUEST_PHASE_KEEPALIVE)&&(client->impl.phase != ANODE_HTTP_REQUEST_PHASE_CLOSED)) {
  146. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_SERVER_CLOSED_CONNECTION;
  147. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED;
  148. AnodeHttpClient_close_and_fail(client);
  149. } else client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED;
  150. }
  151. static void AnodeHttpClient_tcp_receive_handler(
  152. AnodeTransportEngine *transport,
  153. AnodeTransportTcpConnection *connection,
  154. void *data,
  155. unsigned int data_length)
  156. {
  157. struct AnodeHttpClient *client;
  158. char *p1,*p2;
  159. unsigned int i;
  160. long l;
  161. if (!(client = (struct AnodeHttpClient *)(connection->ptr)))
  162. return;
  163. if (client->impl.freed) {
  164. transport->tcp_close(transport,connection);
  165. return;
  166. }
  167. if (!client->response.data)
  168. client->response.data = malloc(client->impl.response_data_capacity = ANODE_HTTP_CAPACITY_INCREMENT);
  169. i = 0;
  170. while (i < data_length) {
  171. switch(client->impl.read_mode) {
  172. case ANODE_HTTP_READ_MODE_WAITING:
  173. for(;i<data_length;++i) {
  174. if (((const char *)data)[i] == '\n') {
  175. ((char *)client->response.data)[client->response.data_length] = (char)0;
  176. client->response.data_length = 0;
  177. p1 = (char *)Anode_strchr((char *)client->response.data,' ');
  178. if (!p1)
  179. p1 = (char *)Anode_strchr((char *)client->response.data,'\t');
  180. if (p1) {
  181. while ((*p1 == ' ')||(*p1 == '\t')) ++p1;
  182. if (!*p1) {
  183. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE;
  184. AnodeHttpClient_close_and_fail(client);
  185. return;
  186. }
  187. p2 = p1 + 1;
  188. while (*p2) {
  189. if ((*p2 == ' ')||(*p2 == '\t')||(*p2 == '\r')||(*p2 == '\n')) {
  190. *p2 = (char)0;
  191. break;
  192. } else ++p2;
  193. }
  194. client->response.code = (int)strtol(p1,(char **)0,10);
  195. client->impl.read_mode = ANODE_HTTP_READ_MODE_HEADERS;
  196. ++i; break; /* Exit inner for() */
  197. }
  198. } else {
  199. ((char *)client->response.data)[client->response.data_length++] = ((const char *)data)[i];
  200. if (client->response.data_length >= client->impl.response_data_capacity)
  201. client->response.data = realloc(client->response.data,client->impl.response_data_capacity += ANODE_HTTP_CAPACITY_INCREMENT);
  202. }
  203. }
  204. break;
  205. case ANODE_HTTP_READ_MODE_HEADERS:
  206. case ANODE_HTTP_READ_MODE_CHUNKED_FOOTER:
  207. for(;i<data_length;++i) {
  208. if (((const char *)data)[i] == '\n') {
  209. client->impl.header_line_buf[client->impl.header_line_buf_ptr] = (char)0;
  210. client->impl.header_line_buf_ptr = 0;
  211. if ((!client->impl.header_line_buf[0])||((client->impl.header_line_buf[0] == '\r')&&(!client->impl.header_line_buf[1]))) {
  212. /* If the line is empty (or is empty with \r\n as the
  213. * line terminator), we're at the end. */
  214. if (client->impl.read_mode == ANODE_HTTP_READ_MODE_CHUNKED_FOOTER) {
  215. /* If this is a chunked footer, we finally end the
  216. * chunked response. */
  217. client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING;
  218. if (client->keepalive)
  219. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE;
  220. else {
  221. client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection);
  222. client->impl.tcp_connection = (AnodeTransportTcpConnection *)0;
  223. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED;
  224. }
  225. if (client->handler)
  226. client->handler(client);
  227. if (client->impl.freed)
  228. return;
  229. } else {
  230. /* Otherwise, this is a regular header block */
  231. if (client->response.code == 100) {
  232. /* Ignore 100 Continue messages */
  233. client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING;
  234. ++i; break; /* Exit inner for() */
  235. } else if ((client->response.code == 200)&&(client->method != ANODE_HTTP_HEAD)) {
  236. /* Other messages get their headers parsed to determine
  237. * how to read them. */
  238. p1 = (char *)AnodeDictionary_get(&(client->response.headers),"transfer-encoding");
  239. if ((p1)&&(Anode_strcaseeq(p1,"chunked"))) {
  240. /* Chunked encoding enters chunked mode */
  241. client->impl.header_line_buf_ptr = 0;
  242. client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_CHUNK_SIZE;
  243. ++i; break; /* Exit inner for() */
  244. } else {
  245. /* Else we must have a Content-Length header */
  246. p1 = (char *)AnodeDictionary_get(&(client->response.headers),"content-length");
  247. if (!p1) {
  248. /* No chunked or content length is not supported */
  249. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE;
  250. AnodeHttpClient_close_and_fail(client);
  251. return;
  252. } else {
  253. /* Enter block read mode with content length */
  254. l = strtol(p1,(char **)0,10);
  255. if (l <= 0) {
  256. /* Zero length data is all done... */
  257. client->impl.expecting_response_length = 0;
  258. client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING;
  259. if (client->keepalive)
  260. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE;
  261. else {
  262. client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection);
  263. client->impl.tcp_connection = (AnodeTransportTcpConnection *)0;
  264. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED;
  265. }
  266. if (client->handler)
  267. client->handler(client);
  268. if (client->impl.freed)
  269. return;
  270. ++i; break; /* Exit inner for() */
  271. } else {
  272. /* Else start reading... */
  273. client->impl.expecting_response_length = (unsigned int)l;
  274. client->impl.read_mode = ANODE_HTTP_READ_MODE_BLOCK;
  275. ++i; break; /* Exit inner for() */
  276. }
  277. }
  278. }
  279. } else {
  280. /* HEAD clients or non-200 codes get headers only */
  281. client->impl.expecting_response_length = 0;
  282. client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING;
  283. if (client->keepalive)
  284. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE;
  285. else {
  286. client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection);
  287. client->impl.tcp_connection = (AnodeTransportTcpConnection *)0;
  288. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED;
  289. }
  290. if (client->handler)
  291. client->handler(client);
  292. if (client->impl.freed)
  293. return;
  294. ++i; break; /* Exit inner for() */
  295. }
  296. }
  297. } else {
  298. /* Otherwise this is another header, add to dictionary */
  299. AnodeDictionary_read(
  300. &(client->response.headers),
  301. client->impl.header_line_buf,
  302. "\r\n",
  303. ": \t",
  304. "",
  305. (char)0,
  306. 1,
  307. 1
  308. );
  309. }
  310. } else {
  311. client->impl.header_line_buf[client->impl.header_line_buf_ptr++] = ((const char *)data)[i];
  312. if (client->impl.header_line_buf_ptr >= sizeof(client->impl.header_line_buf)) {
  313. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE;
  314. AnodeHttpClient_close_and_fail(client);
  315. return;
  316. }
  317. }
  318. }
  319. break;
  320. case ANODE_HTTP_READ_MODE_BLOCK:
  321. if ((client->response.data_length + client->impl.expecting_response_length) > client->impl.response_data_capacity)
  322. client->response.data = realloc(client->response.data,client->impl.response_data_capacity = (client->response.data_length + client->impl.expecting_response_length));
  323. for(;((i<data_length)&&(client->impl.expecting_response_length));++i) {
  324. ((char *)client->response.data)[client->response.data_length++] = ((const char *)data)[i];
  325. --client->impl.expecting_response_length;
  326. }
  327. if (!client->impl.expecting_response_length) {
  328. client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING;
  329. if (client->keepalive)
  330. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_KEEPALIVE;
  331. else {
  332. client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection);
  333. client->impl.tcp_connection = (AnodeTransportTcpConnection *)0;
  334. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CLOSED;
  335. }
  336. if (client->handler)
  337. client->handler(client);
  338. if (client->impl.freed)
  339. return;
  340. }
  341. break;
  342. case ANODE_HTTP_READ_MODE_CHUNKED_CHUNK_SIZE:
  343. for(;i<data_length;++i) {
  344. if (((const char *)data)[i] == '\n') {
  345. client->impl.header_line_buf[client->impl.header_line_buf_ptr] = (char)0;
  346. client->impl.header_line_buf_ptr = 0;
  347. p1 = client->impl.header_line_buf;
  348. while (*p1) {
  349. if ((*p1 == ';')||(*p1 == ' ')||(*p1 == '\r')||(*p1 == '\n')||(*p1 == '\t')) {
  350. *p1 = (char)0;
  351. break;
  352. } else ++p1;
  353. }
  354. if (client->impl.header_line_buf[0]) {
  355. l = strtol(client->impl.header_line_buf,(char **)0,16);
  356. if (l <= 0) {
  357. /* Zero length ends chunked and enters footer mode */
  358. client->impl.expecting_response_length = 0;
  359. client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_FOOTER;
  360. } else {
  361. /* Otherwise the next chunk is to be read */
  362. client->impl.expecting_response_length = (unsigned int)l;
  363. client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_DATA;
  364. }
  365. ++i; break; /* Exit inner for() */
  366. }
  367. } else {
  368. client->impl.header_line_buf[client->impl.header_line_buf_ptr++] = ((const char *)data)[i];
  369. if (client->impl.header_line_buf_ptr >= sizeof(client->impl.header_line_buf)) {
  370. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_INVALID_RESPONSE;
  371. AnodeHttpClient_close_and_fail(client);
  372. return;
  373. }
  374. }
  375. }
  376. break;
  377. case ANODE_HTTP_READ_MODE_CHUNKED_DATA:
  378. if ((client->response.data_length + client->impl.expecting_response_length) > client->impl.response_data_capacity)
  379. client->response.data = realloc(client->response.data,client->impl.response_data_capacity = (client->response.data_length + client->impl.expecting_response_length));
  380. for(;((i<data_length)&&(client->impl.expecting_response_length));++i) {
  381. ((char *)client->response.data)[client->response.data_length++] = ((const char *)data)[i];
  382. --client->impl.expecting_response_length;
  383. }
  384. if (!client->impl.expecting_response_length)
  385. client->impl.read_mode = ANODE_HTTP_READ_MODE_CHUNKED_CHUNK_SIZE;
  386. break;
  387. }
  388. }
  389. }
  390. static void AnodeHttpClient_tcp_available_for_write_handler(
  391. AnodeTransportEngine *transport,
  392. AnodeTransportTcpConnection *connection)
  393. {
  394. struct AnodeHttpClient *client;
  395. unsigned int i,j;
  396. int n;
  397. if (!(client = (struct AnodeHttpClient *)(connection->ptr)))
  398. return;
  399. if (client->impl.freed) {
  400. transport->tcp_close(transport,connection);
  401. return;
  402. }
  403. if (client->impl.phase == ANODE_HTTP_REQUEST_PHASE_SEND) {
  404. n = client->impl.transport_engine->tcp_send(client->impl.transport_engine,client->impl.tcp_connection,(const void *)client->impl.outbuf,(int)client->impl.outbuf_len);
  405. if (n < 0) {
  406. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_SERVER_CLOSED_CONNECTION;
  407. AnodeHttpClient_close_and_fail(client);
  408. } else if (n > 0) {
  409. for(i=0,j=(client->impl.outbuf_len - (unsigned int)n);i<j;++i)
  410. client->impl.outbuf[i] = client->impl.outbuf[i + (unsigned int)n];
  411. client->impl.outbuf_len -= (unsigned int)n;
  412. if ((client->method == ANODE_HTTP_POST)&&(client->data)&&(client->data_length)) {
  413. i = sizeof(client->impl.outbuf) - client->impl.outbuf_len;
  414. j = client->data_length - client->impl.request_data_ptr;
  415. if (i > j)
  416. i = j;
  417. Anode_memcpy((client->impl.outbuf + client->impl.outbuf_len),client->data,i);
  418. client->impl.request_data_ptr += i;
  419. client->impl.outbuf_len += i;
  420. }
  421. if (!client->impl.outbuf_len) {
  422. client->impl.transport_engine->tcp_stop_writing(client->impl.transport_engine,client->impl.tcp_connection);
  423. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_RECEIVE;
  424. }
  425. }
  426. } else client->impl.transport_engine->tcp_stop_writing(client->impl.transport_engine,client->impl.tcp_connection);
  427. }
  428. static void AnodeHttpClient_dns_result_handler(
  429. AnodeTransportEngine *transport,
  430. void *ptr,
  431. int error_code,
  432. const char *name,
  433. const AnodeTransportIpAddress *ip_addresses,
  434. unsigned int ip_address_count,
  435. const AnodeAddress *anode_address)
  436. {
  437. struct AnodeHttpClient *client;
  438. AnodeTransportIpEndpoint to_endpoint;
  439. if (!(client = (struct AnodeHttpClient *)ptr))
  440. return;
  441. if (client->impl.freed)
  442. return;
  443. if ((error_code)||(!ip_address_count)) {
  444. if (client->impl.phase == ANODE_HTTP_REQUEST_PHASE_RESOLVE) {
  445. client->response.code = ANODE_HTTP_SPECIAL_RESPONSE_DNS_RESOLVE_FAILED;
  446. AnodeHttpClient_close_and_fail(client);
  447. }
  448. } else {
  449. client->impl.phase = ANODE_HTTP_REQUEST_PHASE_CONNECT;
  450. Anode_memcpy(&to_endpoint.address,ip_addresses,sizeof(AnodeTransportIpAddress));
  451. to_endpoint.port = (client->uri.port > 0) ? client->uri.port : 80;
  452. client->impl.transport_engine->tcp_connect(
  453. client->impl.transport_engine,
  454. client,
  455. &AnodeHttpClient_tcp_outgoing_connect_handler,
  456. &AnodeHttpClient_tcp_connection_terminated_handler,
  457. &AnodeHttpClient_tcp_receive_handler,
  458. &AnodeHttpClient_tcp_available_for_write_handler,
  459. &to_endpoint);
  460. }
  461. }
  462. struct AnodeHttpClient *AnodeHttpClient_new(AnodeTransportEngine *transport_engine)
  463. {
  464. struct AnodeHttpClient *req = malloc(sizeof(struct AnodeHttpClient));
  465. Anode_zero(req,sizeof(struct AnodeHttpClient));
  466. AnodeDictionary_init(&(req->headers),0);
  467. AnodeDictionary_init(&(req->response.headers),0);
  468. req->impl.transport_engine = transport_engine;
  469. return req;
  470. }
  471. void AnodeHttpClient_send(struct AnodeHttpClient *client)
  472. {
  473. client->response.code = 0;
  474. client->response.data_length = 0;
  475. AnodeDictionary_clear(&(client->response.headers));
  476. client->impl.request_data_ptr = 0;
  477. client->impl.expecting_response_length = 0;
  478. client->impl.read_mode = ANODE_HTTP_READ_MODE_WAITING;
  479. client->impl.outbuf_len = 0;
  480. if (!client->impl.tcp_connection) {
  481. client->impl.transport_engine->dns_resolve(
  482. client->impl.transport_engine,
  483. &AnodeHttpClient_dns_result_handler,
  484. client,
  485. client->uri.host,
  486. ANODE_TRANSPORT_DNS_QUERY_ALWAYS,
  487. ANODE_TRANSPORT_DNS_QUERY_IF_NO_PREVIOUS,
  488. ANODE_TRANSPORT_DNS_QUERY_NEVER);
  489. } else AnodeHttpClient_do_initiate_client(client);
  490. }
  491. void AnodeHttpClient_free(struct AnodeHttpClient *client)
  492. {
  493. AnodeDictionary_destroy(&(client->headers));
  494. AnodeDictionary_destroy(&(client->response.headers));
  495. if (client->impl.tcp_connection) {
  496. client->impl.transport_engine->tcp_close(client->impl.transport_engine,client->impl.tcp_connection);
  497. client->impl.tcp_connection = (AnodeTransportTcpConnection *)0;
  498. }
  499. if (client->response.data)
  500. free(client->response.data);
  501. client->impl.freed = 1;
  502. client->impl.transport_engine->run_later(client->impl.transport_engine,client,&free);
  503. }