PageRenderTime 67ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/platform/FNET/fnet_stack/services/http/fnet_http.c

https://gitlab.com/fuggles/ucos
C | 1209 lines | 829 code | 171 blank | 209 comment | 194 complexity | b59e8bbf57782b26fb2cc8b36a58a839 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /**************************************************************************
  2. *
  3. * Copyright 2011-2015 by Andrey Butok. FNET Community.
  4. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
  5. *
  6. ***************************************************************************
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License Version 3
  9. * or later (the "LGPL").
  10. *
  11. * As a special exception, the copyright holders of the FNET project give you
  12. * permission to link the FNET sources with independent modules to produce an
  13. * executable, regardless of the license terms of these independent modules,
  14. * and to copy and distribute the resulting executable under terms of your
  15. * choice, provided that you also meet, for each linked independent module,
  16. * the terms and conditions of the license of that module.
  17. * An independent module is a module which is not derived from or based
  18. * on this library.
  19. * If you modify the FNET sources, you may extend this exception
  20. * to your version of the FNET sources, but you are not obligated
  21. * to do so. If you do not wish to do so, delete this
  22. * exception statement from your version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  27. *
  28. * You should have received a copy of the GNU General Public License
  29. * and the GNU Lesser General Public License along with this program.
  30. * If not, see <http://www.gnu.org/licenses/>.
  31. *
  32. **********************************************************************/ /*!
  33. *
  34. * @file fnet_http.c
  35. *
  36. * @author Andrey Butok
  37. *
  38. * @brief FNET HTTP/0.9 Server implementation.
  39. *
  40. ***************************************************************************/
  41. #include "fnet.h"
  42. #if FNET_CFG_HTTP
  43. #include "fnet_http_prv.h"
  44. #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
  45. #include "fnet_http_auth_prv.h"
  46. #endif
  47. /************************************************************************
  48. * Definitions
  49. ************************************************************************/
  50. /* Automated time-outs */
  51. #define FNET_HTTP_WAIT_TX_MS (10000) /* ms*/
  52. #define FNET_HTTP_WAIT_RX_MS (15000) /* ms*/
  53. #define FNET_HTTP_BACKLOG_MAX (FNET_CFG_HTTP_SESSION_MAX)
  54. #define FNET_HTTP_VERSION_HEADER "HTTP/" /* Protocol version HTTP/x.x*/
  55. #define FNET_HTTP_ITERATION_NUMBER (2)
  56. #define FNET_HTTP_HEADER_FIELD_CONTENT_TYPE "Content-Type:"
  57. #define FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH "Content-Length:"
  58. #define FNET_HTTP_HEADER_FIELD_AUTHENTICATE "WWW-Authenticate:"
  59. #define FNET_HTTP_HEADER_FIELD_AUTHORIZATION "Authorization:"
  60. /* Supported method list. */
  61. static const struct fnet_http_method *fnet_http_method_list[] =
  62. {
  63. &fnet_http_method_get, /* GET method. */
  64. #if FNET_CFG_HTTP_POST
  65. &fnet_http_method_post, /* POST method. */
  66. #endif
  67. 0 /* End of the list */
  68. };
  69. /* File handler list.`*/
  70. static const struct fnet_http_file_handler *fnet_http_file_handler_list[] =
  71. {
  72. #if FNET_CFG_HTTP_SSI
  73. &fnet_http_ssi_handler, /* SSI handler */
  74. #endif
  75. #if FNET_CFG_HTTP_CGI
  76. &fnet_http_cgi_handler, /* CGI handler */
  77. #endif
  78. /* Add your file-handler here.*/
  79. 0
  80. };
  81. /* Default file handler.*/
  82. static const struct fnet_http_file_handler fnet_http_default_handler =
  83. {
  84. "", fnet_http_default_handle,
  85. fnet_http_default_send,
  86. fnet_http_default_close
  87. };
  88. /*File extension*/ /* MIME type*/
  89. const struct fnet_http_content_type fnet_http_content_css = {"css", "text/css"};
  90. const struct fnet_http_content_type fnet_http_content_jpg = {"jpg", "image/jpeg"};
  91. const struct fnet_http_content_type fnet_http_content_gif = {"gif", "image/gif"};
  92. const struct fnet_http_content_type fnet_http_content_js = {"js", "application/javascript"};
  93. const struct fnet_http_content_type fnet_http_content_gzip = {"gz", "application/x-gzip"};
  94. const struct fnet_http_content_type fnet_http_content_zip = {"zip", "application/zip"};
  95. /************************************************************************
  96. * File content-type list.
  97. *************************************************************************/
  98. const struct fnet_http_content_type *fnet_http_content_type_list[] =
  99. {
  100. &fnet_http_content_css,
  101. &fnet_http_content_jpg,
  102. &fnet_http_content_gif,
  103. &fnet_http_content_js,
  104. &fnet_http_content_gzip,
  105. &fnet_http_content_zip,
  106. /* Add your content-type here. */
  107. 0
  108. };
  109. /* The HTTP interface */
  110. static struct fnet_http_if http_if_list[FNET_CFG_HTTP_MAX];
  111. static void fnet_http_state_machine( void *http_if_p );
  112. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  113. /************************************************************************
  114. * HTTP response status list.
  115. *************************************************************************/
  116. struct fnet_http_status fnet_http_status_list[] =
  117. {
  118. {FNET_HTTP_STATUS_CODE_OK, FNET_HTTP_REASON_PHRASE_OK},
  119. {FNET_HTTP_STATUS_CODE_CREATED, FNET_HTTP_REASON_PHRASE_CREATED},
  120. {FNET_HTTP_STATUS_CODE_ACCEPTED, FNET_HTTP_REASON_PHRASE_ACCEPTED},
  121. {FNET_HTTP_STATUS_CODE_NO_CONTENT, FNET_HTTP_REASON_PHRASE_NO_CONTENT},
  122. {FNET_HTTP_STATUS_CODE_MOVED_PERMANENTLY, FNET_HTTP_REASON_PHRASE_MOVED_PERMANENTLY},
  123. {FNET_HTTP_STATUS_CODE_MOVED_TEMPORARILY, FNET_HTTP_REASON_PHRASE_MOVED_TEMPORARILY},
  124. {FNET_HTTP_STATUS_CODE_NOT_MODIFIED, FNET_HTTP_REASON_PHRASE_NOT_MODIFIED},
  125. {FNET_HTTP_STATUS_CODE_BAD_REQUEST, FNET_HTTP_REASON_PHRASE_BAD_REQUEST},
  126. {FNET_HTTP_STATUS_CODE_UNAUTHORIZED, FNET_HTTP_REASON_PHRASE_UNAUTHORIZED},
  127. {FNET_HTTP_STATUS_CODE_FORBIDDEN, FNET_HTTP_REASON_PHRASE_FORBIDDEN},
  128. {FNET_HTTP_STATUS_CODE_NOT_FOUND, FNET_HTTP_REASON_PHRASE_NOT_FOUND},
  129. {FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR, FNET_HTTP_REASON_PHRASE_INTERNAL_SERVER_ERROR},
  130. {FNET_HTTP_STATUS_CODE_NOT_IMPLEMENTED, FNET_HTTP_REASON_PHRASE_NOT_IMPLEMENTED},
  131. {FNET_HTTP_STATUS_CODE_BAD_GATEWAY, FNET_HTTP_REASON_PHRASE_BAD_GATEWAY},
  132. {FNET_HTTP_STATUS_CODE_SERVICE_UNAVAILABLE, FNET_HTTP_REASON_PHRASE_SERVICE_UNAVAILABLE},
  133. {FNET_HTTP_STATUS_CODE_NONE, ""} /* End of the list.*/
  134. };
  135. static void fnet_http_version_parse(char * in_str, struct fnet_http_version * version);
  136. static int fnet_http_tx_status_line (struct fnet_http_if * http);
  137. static int fnet_http_status_ok(int status);
  138. #endif /* FNET_CFG_HTTP_VERSION_MAJOR */
  139. /************************************************************************
  140. * NAME: fnet_http_state_machine
  141. *
  142. * DESCRIPTION: Http server state machine.
  143. ************************************************************************/
  144. static void fnet_http_state_machine( void *http_if_p )
  145. {
  146. struct sockaddr foreign_addr;
  147. unsigned int len;
  148. int res;
  149. struct fnet_http_if *http = (struct fnet_http_if *)http_if_p;
  150. int iteration;
  151. char *ch;
  152. int i;
  153. struct fnet_http_session_if *session;
  154. for(i=0; i<FNET_CFG_HTTP_SESSION_MAX; i++)
  155. {
  156. session = &http->session[i];
  157. http->session_active = session;
  158. for(iteration = 0; iteration < FNET_HTTP_ITERATION_NUMBER; iteration++)
  159. {
  160. switch(session->state)
  161. {
  162. /*---- LISTENING ------------------------------------------------*/
  163. case FNET_HTTP_STATE_LISTENING:
  164. len = sizeof(foreign_addr);
  165. if((session->socket_foreign = accept(http->socket_listen, &foreign_addr, &len)) != SOCKET_INVALID)
  166. {
  167. #if FNET_CFG_DEBUG_HTTP
  168. {
  169. char ip_str[FNET_IP_ADDR_STR_SIZE];
  170. fnet_inet_ntop(foreign_addr.sa_family, (char*)(foreign_addr.sa_data), ip_str, sizeof(ip_str));
  171. FNET_DEBUG_HTTP("");
  172. FNET_DEBUG_HTTP("HTTP: RX Request From: %s; Port: %d.", ip_str, fnet_ntohs(foreign_addr.sa_port));
  173. }
  174. #endif
  175. /* Reset response & request parameters.*/
  176. fnet_memset_zero(&session->response, sizeof(struct fnet_http_response));
  177. fnet_memset_zero(&session->request, sizeof(struct fnet_http_request));
  178. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  179. session->response.content_length = -1; /* No content length by default.*/
  180. /* Default HTTP version response.*/
  181. session->response.version.major = FNET_HTTP_VERSION_MAJOR;
  182. session->response.version.minor = FNET_HTTP_VERSION_MINOR;
  183. session->response.tx_data = fnet_http_tx_status_line;
  184. #endif
  185. session->state_time = fnet_timer_ticks(); /* Reset timeout. */
  186. session->buffer_actual_size = 0;
  187. session->state = FNET_HTTP_STATE_RX_REQUEST; /* => WAITING HTTP REQUEST */
  188. }
  189. break;
  190. /*---- RX_LINE -----------------------------------------------*/
  191. case FNET_HTTP_STATE_RX_REQUEST:
  192. do
  193. {
  194. /* Read character by character.*/
  195. ch = &session->buffer[session->buffer_actual_size];
  196. if((res = recv(session->socket_foreign, ch, 1, 0) )!= SOCKET_ERROR)
  197. {
  198. if(res > 0) /* Received a data.*/
  199. {
  200. session->state_time = fnet_timer_ticks(); /* Reset timeout.*/
  201. session->buffer_actual_size++;
  202. if(*ch == '\r')
  203. *ch = '\0';
  204. else if(*ch == '\n')
  205. /* Line received.*/
  206. {
  207. char * req_buf = &session->buffer[0];
  208. *ch = '\0';
  209. if(session->request.method == 0)
  210. /* Parse Request line.*/
  211. {
  212. const struct fnet_http_method **method = &fnet_http_method_list[0];
  213. FNET_DEBUG_HTTP("HTTP: RX Request: %s", req_buf);
  214. /* Determine the method type. */
  215. while(*method)
  216. {
  217. if ( !fnet_strcmp_splitter(req_buf, (*method)->token, ' ') )
  218. {
  219. req_buf+=fnet_strlen((*method)->token);
  220. session->request.method = *method;
  221. break;
  222. }
  223. method++;
  224. }
  225. /* Check if the method is supported? */
  226. if(session->request.method && session->request.method->handle)
  227. {
  228. /* Parse URI.*/
  229. req_buf = fnet_http_uri_parse(req_buf, &session->request.uri);
  230. FNET_DEBUG_HTTP("HTTP: URI Path = %s; Query = %s", session->request.uri.path, session->request.uri.query);
  231. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  232. /* Parse HTTP/x.x version.*/
  233. fnet_http_version_parse(++req_buf, &session->response.version);
  234. /* Check the highest supported HTTP version.*/
  235. if(((session->response.version.major<<8)|session->response.version.minor) > ((FNET_HTTP_VERSION_MAJOR<<8)|FNET_HTTP_VERSION_MINOR))
  236. {
  237. session->response.version.major = FNET_HTTP_VERSION_MAJOR;
  238. session->response.version.minor = FNET_HTTP_VERSION_MINOR;
  239. }
  240. if(session->response.version.major == 0)
  241. /* HTTP/0.x */
  242. {
  243. session->state = FNET_HTTP_STATE_CLOSING; /* Client does not support HTTP/1.x*/
  244. break;
  245. }
  246. #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
  247. /* Check Authentification.*/
  248. fnet_http_auth_validate_uri(http);
  249. #endif
  250. #endif/*FNET_CFG_HTTP_VERSION_MAJOR*/
  251. /* Call method initial handler.*/
  252. res = session->request.method->handle(http, &session->request.uri);
  253. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  254. if(fnet_http_status_ok(res) == FNET_OK)
  255. #else
  256. if((res == FNET_OK))
  257. #endif
  258. {
  259. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  260. session->buffer_actual_size = 0;
  261. /* => Parse Header line.*/
  262. #else /* HTTP/0.9 */
  263. session->response.tx_data = session->request.method->send;
  264. /* Reset buffer pointers.*/
  265. session->buffer_actual_size = 0;
  266. session->state = FNET_HTTP_STATE_TX; /* Send data.*/
  267. #endif
  268. }
  269. /* Method error.*/
  270. else /* Error.*/
  271. {
  272. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  273. /* Default code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR. */
  274. if(res != FNET_ERR)
  275. session->response.status.code = (fnet_http_status_code_t)res;
  276. /* Send status line.*/
  277. session->buffer_actual_size = 0;
  278. session->state = FNET_HTTP_STATE_TX; /* Send error.*/
  279. #else /* HTTP/0.9 */
  280. session->state = FNET_HTTP_STATE_CLOSING;
  281. #endif
  282. }
  283. }
  284. /* Method is not supported.*/
  285. else /* Error.*/
  286. {
  287. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  288. session->response.status.code = FNET_HTTP_STATUS_CODE_NOT_IMPLEMENTED;
  289. /* Send status line.*/
  290. session->buffer_actual_size = 0;
  291. session->state = FNET_HTTP_STATE_TX; /* Send error.*/
  292. #else /* HTTP/0.9 */
  293. session->state = FNET_HTTP_STATE_CLOSING;
  294. #endif
  295. }
  296. }
  297. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  298. /* Parse Header line.*/
  299. else
  300. {
  301. if(session->request.skip_line == 0)
  302. {
  303. if(*req_buf == 0)
  304. /* === Empty line => End of the request header. ===*/
  305. {
  306. #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
  307. if(session->response.auth_entry)
  308. /* Send UNAUTHORIZED error.*/
  309. session->response.status.code = FNET_HTTP_STATUS_CODE_UNAUTHORIZED;
  310. else /* Send Data.*/
  311. #endif
  312. session->response.status.code = FNET_HTTP_STATUS_CODE_OK;
  313. #if FNET_CFG_HTTP_POST
  314. if(session->request.content_length > 0)
  315. /* RX Entity-Body.*/
  316. {
  317. session->buffer_actual_size = 0;
  318. session->state = FNET_HTTP_STATE_RX;
  319. }
  320. else
  321. #endif
  322. /* TX Full-Responce.*/
  323. {
  324. /* Send status line.*/
  325. session->buffer_actual_size = 0;
  326. session->state = FNET_HTTP_STATE_TX;
  327. }
  328. break;
  329. }
  330. else
  331. /* === Parse header fields. ===*/
  332. {
  333. FNET_DEBUG_HTTP("HTTP: RX Header: %s", req_buf);
  334. #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
  335. /* --- Authorization: ---*/
  336. if (session->response.auth_entry && fnet_strncmp(req_buf, FNET_HTTP_HEADER_FIELD_AUTHORIZATION, sizeof(FNET_HTTP_HEADER_FIELD_AUTHORIZATION)-1) == 0)
  337. /* Authetication is required.*/
  338. {
  339. char *auth_str = &req_buf[sizeof(FNET_HTTP_HEADER_FIELD_AUTHORIZATION)-1];
  340. /* Validate credentials.*/
  341. if(fnet_http_auth_validate_credentials(http, auth_str) == FNET_OK)
  342. session->response.auth_entry = 0; /* Authorization is succesful.*/
  343. }
  344. #endif
  345. #if FNET_CFG_HTTP_POST
  346. /* --- Content-Length: ---*/
  347. if (session->request.method->receive && fnet_strncmp(req_buf, FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH, sizeof(FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH)-1) == 0)
  348. {
  349. char *p;
  350. char *length_str = &req_buf[sizeof(FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH)-1];
  351. session->request.content_length = (long)fnet_strtoul(length_str,&p,10);
  352. }
  353. #endif
  354. }
  355. }
  356. /* Line is skiped.*/
  357. else
  358. session->request.skip_line = 0; /* Reset the Skip flag.*/
  359. session->buffer_actual_size = 0; /* => Parse Next Header line.*/
  360. }
  361. #endif/* FNET_CFG_HTTP_VERSION_MAJOR */
  362. }
  363. /* Not whole line received yet.*/
  364. else if (session->buffer_actual_size == FNET_HTTP_BUF_SIZE)
  365. /* Buffer is full.*/
  366. {
  367. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  368. if(session->request.method != 0)
  369. /* For header, skip the line.*/
  370. {
  371. /* Skip line.*/
  372. session->request.skip_line = 1;
  373. session->buffer_actual_size = 0;
  374. }
  375. else /* Error.*/
  376. {
  377. /* Default code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR. */
  378. session->buffer_actual_size = 0;
  379. session->state = FNET_HTTP_STATE_TX; /* Send error.*/
  380. }
  381. #else /* HTTP/0.9 */
  382. session->state = FNET_HTTP_STATE_CLOSING;
  383. #endif
  384. }
  385. }
  386. /* No data.*/
  387. else if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks()) /* Time out? */
  388. > (FNET_HTTP_WAIT_RX_MS / FNET_TIMER_PERIOD_MS))
  389. {
  390. session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
  391. }
  392. /* else => WAITING REQUEST. */
  393. }
  394. /* recv() error.*/
  395. else
  396. {
  397. session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
  398. }
  399. }
  400. while ((res > 0) && (session->state == FNET_HTTP_STATE_RX_REQUEST)); /* Till receiving the request header.*/
  401. break;
  402. #if FNET_CFG_HTTP_POST
  403. /*---- RX --------------------------------------------------*/
  404. case FNET_HTTP_STATE_RX: /* Receive data (Entity-Body). */
  405. if((res = recv(session->socket_foreign, &session->buffer[session->buffer_actual_size], (int)(FNET_HTTP_BUF_SIZE-session->buffer_actual_size), 0) )!= SOCKET_ERROR)
  406. {
  407. session->buffer_actual_size += res;
  408. session->request.content_length -= res;
  409. if(res > 0)
  410. /* Some Data.*/
  411. {
  412. session->state_time = fnet_timer_ticks(); /* Reset timeout.*/
  413. res = session->request.method->receive(http);
  414. if(fnet_http_status_ok(res) != FNET_OK)
  415. {
  416. if(res != FNET_ERR)
  417. session->response.status.code = (fnet_http_status_code_t)res;
  418. else
  419. session->response.status.code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR;
  420. session->request.content_length = 0;
  421. }
  422. if(session->request.content_length <= 0) /* The last data.*/
  423. {
  424. session->state = FNET_HTTP_STATE_TX; /* Send data.*/
  425. }
  426. session->buffer_actual_size = 0;
  427. }
  428. else
  429. /* No Data.*/
  430. {
  431. if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks())
  432. > (FNET_HTTP_WAIT_RX_MS / FNET_TIMER_PERIOD_MS))
  433. /* Time out.*/
  434. {
  435. session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
  436. }
  437. }
  438. }
  439. else
  440. /* Socket error.*/
  441. {
  442. session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
  443. }
  444. break;
  445. #endif /* FNET_CFG_HTTP_POST.*/
  446. /*---- TX --------------------------------------------------*/
  447. case FNET_HTTP_STATE_TX: /* Send data. */
  448. if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks())
  449. < (FNET_HTTP_WAIT_TX_MS / FNET_TIMER_PERIOD_MS)) /* Check timeout */
  450. {
  451. int send_size;
  452. if(session->buffer_actual_size == session->response.buffer_sent)
  453. {
  454. /* Reset counters.*/
  455. session->buffer_actual_size =0;
  456. session->response.buffer_sent = 0;
  457. if(session->response.send_eof || session->response.tx_data(http) == FNET_ERR) /* get data for sending */
  458. {
  459. session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
  460. break;
  461. }
  462. }
  463. send_size = (int)(session->buffer_actual_size - (int)session->response.buffer_sent);
  464. if(send_size > http->send_max)
  465. send_size = (int)http->send_max;
  466. if((res = send(session->socket_foreign, session->buffer
  467. + session->response.buffer_sent, send_size, 0)) != SOCKET_ERROR)
  468. {
  469. if(res)
  470. {
  471. FNET_DEBUG_HTTP("HTTP: TX %d bytes.", res);
  472. session->state_time = fnet_timer_ticks(); /* reset timeout */
  473. session->response.buffer_sent += res;
  474. }
  475. break; /* => SENDING */
  476. }
  477. }
  478. session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
  479. break;
  480. /*---- CLOSING --------------------------------------------------*/
  481. case FNET_HTTP_STATE_CLOSING:
  482. if(session->request.method && session->request.method->close)
  483. session->request.method->close(http);
  484. closesocket(session->socket_foreign);
  485. session->socket_foreign = SOCKET_INVALID;
  486. session->state = FNET_HTTP_STATE_LISTENING; /*=> LISTENING */
  487. break;
  488. default:
  489. break;
  490. }
  491. }
  492. } /*for(sessions)*/
  493. }
  494. /************************************************************************
  495. * NAME: fnet_http_init
  496. *
  497. * DESCRIPTION: Initialization of the HTTP server.
  498. *************************************************************************/
  499. fnet_http_desc_t fnet_http_init( struct fnet_http_params *params )
  500. {
  501. struct sockaddr local_addr;
  502. struct fnet_http_uri uri;
  503. int i;
  504. struct fnet_http_if *http_if = 0;
  505. const struct linger linger_option ={1, /*l_onoff*/
  506. 4 /*l_linger*/};
  507. unsigned int opt_len;
  508. if(params == 0 || params->root_path == 0 || params->index_path == 0)
  509. {
  510. FNET_DEBUG_HTTP("HTTP: Wrong init parameters.");
  511. goto ERROR_1;
  512. }
  513. /* Try to find free HTTP server. */
  514. #if (FNET_CFG_HTTP_MAX > 1)
  515. for(i=0; i<FNET_CFG_HTTP_MAX; i++)
  516. {
  517. if(http_if_list[i].enabled == FNET_FALSE)
  518. {
  519. http_if = &http_if_list[i];
  520. break
  521. }
  522. }
  523. #else
  524. if(http_if_list[0].enabled == FNET_FALSE)
  525. http_if = &http_if_list[0];
  526. #endif
  527. /* Is HTTP server already initialized. */
  528. if(http_if == 0)
  529. {
  530. FNET_DEBUG_HTTP("HTTP: No free HTTP Server.");
  531. goto ERROR_1;
  532. }
  533. #if FNET_CFG_HTTP_SSI
  534. http_if->ssi.ssi_table = params->ssi_table;
  535. #endif
  536. #if FNET_CFG_HTTP_CGI
  537. http_if->cgi_table = params->cgi_table;
  538. #endif
  539. #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
  540. http_if->auth_table = params->auth_table;
  541. #endif
  542. #if FNET_CFG_HTTP_POST
  543. http_if->post_table = params->post_table;
  544. #endif
  545. local_addr = params->address;
  546. if(local_addr.sa_port == 0)
  547. local_addr.sa_port = FNET_CFG_HTTP_PORT; /* Aply the default port.*/
  548. if(local_addr.sa_family == AF_UNSPEC)
  549. local_addr.sa_family = AF_SUPPORTED; /* Asign supported families.*/
  550. /* Create listen socket */
  551. if((http_if->socket_listen = socket(local_addr.sa_family, SOCK_STREAM, 0)) == SOCKET_INVALID)
  552. {
  553. FNET_DEBUG_HTTP("HTTP: Socket creation error.");
  554. goto ERROR_1;
  555. }
  556. /* Bind.*/
  557. if(bind(http_if->socket_listen, &local_addr, sizeof(local_addr)) == SOCKET_ERROR)
  558. {
  559. FNET_DEBUG_HTTP("HTTP: Socket bind error.");
  560. goto ERROR_2;
  561. }
  562. /* Set socket options.*/
  563. setsockopt (http_if->socket_listen, SOL_SOCKET, SO_LINGER,
  564. (char *) &linger_option, sizeof(linger_option));
  565. /* Get size of the socket send buffer */
  566. opt_len = sizeof(http_if->send_max);
  567. if(getsockopt(http_if->socket_listen, SOL_SOCKET, SO_SNDBUF,
  568. (char *) &http_if->send_max, &opt_len) == SOCKET_ERROR)
  569. {
  570. FNET_DEBUG_HTTP("HTTP: Socket getsockopt() error.");
  571. goto ERROR_2;
  572. }
  573. /* Listen.*/
  574. if(listen(http_if->socket_listen, FNET_HTTP_BACKLOG_MAX) == SOCKET_ERROR)
  575. {
  576. FNET_DEBUG_HTTP("HTTP: Socket listen error.");
  577. goto ERROR_2;
  578. }
  579. /* Open root dir. */
  580. http_if->root_dir = fnet_fs_opendir(params->root_path);
  581. if(http_if->root_dir == 0)
  582. {
  583. FNET_DEBUG_HTTP("HTTP: Root directory is failed.");
  584. goto ERROR_2;
  585. }
  586. /* Open index file. */
  587. http_if->index_file = fnet_fs_fopen_re(params->index_path,"r", http_if->root_dir);
  588. if(http_if->index_file == 0)
  589. {
  590. FNET_DEBUG_HTTP("HTTP: Root directory is failed.");
  591. goto ERROR_3;
  592. }
  593. fnet_http_uri_parse(params->index_path, &uri);
  594. http_if->index_file_handler = fnet_http_find_handler(http_if, &uri); /* Find Handler for the index file. */
  595. #if FNET_CFG_HTTP_VERSION_MAJOR
  596. http_if->index_file_content_type = fnet_http_find_content_type(http_if, &uri); /* Find Content-Type for the index file. */
  597. #endif
  598. /* Init session parameters.*/
  599. for(i=0; i<FNET_CFG_HTTP_SESSION_MAX; i++)
  600. {
  601. struct fnet_http_session_if *session = &http_if->session[i];
  602. session->socket_foreign = SOCKET_INVALID;
  603. session->state = FNET_HTTP_STATE_LISTENING;
  604. }
  605. http_if->service_descriptor = fnet_poll_service_register(fnet_http_state_machine, (void *) http_if);
  606. if(http_if->service_descriptor == (fnet_poll_desc_t)FNET_ERR)
  607. {
  608. FNET_DEBUG_HTTP("HTTP: Service registration error.");
  609. goto ERROR_4;
  610. }
  611. http_if->session_active = FNET_NULL;
  612. http_if->enabled = FNET_TRUE;
  613. return (fnet_http_desc_t)http_if;
  614. ERROR_4:
  615. fnet_fs_fclose(http_if->index_file);
  616. ERROR_3:
  617. fnet_fs_closedir(http_if->root_dir);
  618. ERROR_2:
  619. closesocket(http_if->socket_listen);
  620. ERROR_1:
  621. return FNET_ERR;
  622. }
  623. /************************************************************************
  624. * NAME: fnet_http_release
  625. *
  626. * DESCRIPTION: HTTP server release.
  627. ************************************************************************/
  628. void fnet_http_release(fnet_http_desc_t desc)
  629. {
  630. struct fnet_http_if *http_if = (struct fnet_http_if *) desc;
  631. int i;
  632. if(http_if && (http_if->enabled == FNET_TRUE))
  633. {
  634. for(i=0; i<FNET_CFG_HTTP_SESSION_MAX; i++)
  635. {
  636. struct fnet_http_session_if *session = &http_if->session[i];
  637. closesocket(session->socket_foreign);
  638. session->socket_foreign = SOCKET_INVALID;
  639. session->state = FNET_HTTP_STATE_DISABLED;
  640. fnet_fs_fclose(session->send_param.file_desc);
  641. }
  642. fnet_fs_fclose(http_if->index_file);
  643. fnet_fs_closedir(http_if->root_dir);
  644. closesocket(http_if->socket_listen);
  645. fnet_poll_service_unregister(http_if->service_descriptor); /* Delete service.*/
  646. http_if->enabled = FNET_FALSE;
  647. }
  648. }
  649. /************************************************************************
  650. * NAME: fnet_http_enabled
  651. *
  652. * DESCRIPTION: This function returns FNET_TRUE if the HTTP server
  653. * is enabled/initialised.
  654. ************************************************************************/
  655. int fnet_http_enabled(fnet_http_desc_t desc)
  656. {
  657. struct fnet_http_if *http_if = (struct fnet_http_if *) desc;
  658. int result;
  659. if(http_if)
  660. result = http_if->enabled;
  661. else
  662. result = FNET_FALSE;
  663. return result;
  664. }
  665. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  666. /************************************************************************
  667. * NAME: fnet_http_tx_status_line
  668. *
  669. * DESCRIPTION:
  670. ************************************************************************/
  671. static int fnet_http_tx_status_line (struct fnet_http_if * http)
  672. {
  673. struct fnet_http_status *status ;
  674. unsigned long result = 0;
  675. unsigned long result_state;
  676. struct fnet_http_session_if *session = http->session_active;
  677. session->response.send_eof = 0; /* Data to be sent.*/
  678. do
  679. {
  680. result_state = 0;
  681. switch(session->response.status_line_state)
  682. {
  683. case 0:
  684. if(session->response.status.code == 0)
  685. { /* If the code was not found, produce a 501 internal server error */
  686. session->response.status.code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR;
  687. session->response.status.phrase = 0;
  688. }
  689. if(session->response.status.phrase == 0) /* If no phrase is defined.*/
  690. {
  691. for(status = fnet_http_status_list; status->code > 0; status++) /* Find phrase.*/
  692. {
  693. if (status->code == session->response.status.code)
  694. {
  695. break;
  696. }
  697. }
  698. session->response.status.phrase = status->phrase; /* If no phrase is fond it will pont to empty string.*/
  699. }
  700. /* Print status line.*/
  701. result_state = (unsigned long)fnet_snprintf(session->buffer, FNET_HTTP_BUF_SIZE, "%s%d.%d %d %s%s", FNET_HTTP_VERSION_HEADER, session->response.version.major, session->response.version.minor,
  702. session->response.status.code, session->response.status.phrase,
  703. "\r\n");
  704. break;
  705. /* Add HTTP header fields where applicable. */
  706. case 1:
  707. #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
  708. /* Authentificate.*/
  709. if(session->response.status.code == FNET_HTTP_STATUS_CODE_UNAUTHORIZED)
  710. {
  711. result_state = (unsigned long)fnet_snprintf(&session->buffer[result], (FNET_HTTP_BUF_SIZE - result), "%s ", FNET_HTTP_HEADER_FIELD_AUTHENTICATE);
  712. result_state += fnet_http_auth_generate_challenge(http, &session->buffer[result+result_state], FNET_HTTP_BUF_SIZE - (result + result_state));
  713. session->response.content_length = -1; /* No content length .*/
  714. }
  715. #endif
  716. break;
  717. case 2:
  718. /* Content-Length */
  719. if(session->response.content_length >= 0)
  720. {
  721. result_state = (unsigned long)fnet_snprintf(&session->buffer[result], (FNET_HTTP_BUF_SIZE - result), "%s %d%s", FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH, session->response.content_length, "\r\n");
  722. }
  723. break;
  724. case 3:
  725. /* Add MIME Content Type field, based on file extension.*/
  726. if(session->response.send_file_content_type)
  727. {
  728. result_state = (unsigned long)fnet_snprintf(&session->buffer[result],
  729. (FNET_HTTP_BUF_SIZE - result), "%s %s%s",
  730. FNET_HTTP_HEADER_FIELD_CONTENT_TYPE, session->response.send_file_content_type->content_type,"\r\n");
  731. }
  732. break;
  733. case 4:
  734. /*Final CRLF.*/
  735. result_state = (unsigned long)fnet_snprintf(&session->buffer[result], (FNET_HTTP_BUF_SIZE - result),"%s","\r\n");
  736. if(session->response.status.code != FNET_HTTP_STATUS_CODE_OK)
  737. session->response.send_eof = 1; /* Only sataus (without data).*/
  738. session->response.tx_data = session->request.method->send;
  739. break;
  740. }
  741. if((result+result_state) == (FNET_HTTP_BUF_SIZE-1)) /* Buffer overload.*/
  742. {
  743. if(result == 0)
  744. {
  745. fnet_sprintf(&session->buffer[FNET_HTTP_BUF_SIZE-2], "%s","\r\n"); /* Finish line.*/
  746. session->response.status_line_state++;
  747. }
  748. /* else. Do not send last state data.*/
  749. break; /* Send data.*/
  750. }
  751. else
  752. {
  753. result += result_state;
  754. session->response.status_line_state++;
  755. }
  756. }
  757. while (session->response.status_line_state <= 4);
  758. session->buffer_actual_size = result;
  759. FNET_DEBUG_HTTP("HTTP: TX Status: %s", session->buffer);
  760. return FNET_OK;
  761. }
  762. #endif /* FNET_CFG_HTTP_VERSION_MAJOR */
  763. /************************************************************************
  764. * NAME: fnet_http_find_handler
  765. *
  766. * DESCRIPTION:
  767. ************************************************************************/
  768. const struct fnet_http_file_handler * fnet_http_find_handler (struct fnet_http_if * http, struct fnet_http_uri * uri)
  769. {
  770. const struct fnet_http_file_handler * result = &fnet_http_default_handler;
  771. const struct fnet_http_file_handler **handler = &fnet_http_file_handler_list[0];
  772. if(uri)
  773. {
  774. if (!fnet_strcmp(uri->path, "/")) /* Default index file. */
  775. {
  776. result = http->index_file_handler;
  777. }
  778. else
  779. {
  780. while(*handler)
  781. {
  782. if ( !fnet_strcmp( uri->extension, (*handler)->file_extension) )
  783. {
  784. result = *handler;
  785. break;
  786. }
  787. handler++;
  788. }
  789. }
  790. }
  791. return result;
  792. }
  793. /************************************************************************
  794. * NAME: fnet_http_find_content_type
  795. *
  796. * DESCRIPTION:
  797. ************************************************************************/
  798. #if FNET_CFG_HTTP_VERSION_MAJOR
  799. const struct fnet_http_content_type *fnet_http_find_content_type (struct fnet_http_if * http, struct fnet_http_uri * uri)
  800. {
  801. const struct fnet_http_content_type **content_type = &fnet_http_content_type_list[0];
  802. const struct fnet_http_content_type *result = FNET_NULL;
  803. if(uri)
  804. {
  805. if (!fnet_strcmp(uri->path, "/")) /* Default index file. */
  806. {
  807. result = http->index_file_content_type;
  808. }
  809. else
  810. {
  811. while(*content_type)
  812. {
  813. if ( !fnet_strcmp(uri->extension, (*content_type)->file_extension))
  814. {
  815. result = *content_type;
  816. break;
  817. }
  818. content_type++;
  819. }
  820. }
  821. }
  822. return result;
  823. }
  824. #endif /* FNET_CFG_HTTP_VERSION_MAJOR */
  825. /************************************************************************
  826. * NAME: fnet_http_default_send
  827. *
  828. * DESCRIPTION:
  829. ************************************************************************/
  830. int fnet_http_default_handle (struct fnet_http_if * http, struct fnet_http_uri * uri)
  831. {
  832. int result;
  833. struct fnet_http_session_if *session = http->session_active;
  834. if (!fnet_strcmp(uri->path, "/")) /* Default index file */
  835. {
  836. fnet_fs_rewind(http->index_file);
  837. session->send_param.file_desc = http->index_file;
  838. }
  839. else
  840. {
  841. session->send_param.file_desc = fnet_fs_fopen_re(uri->path,"r", http->root_dir);
  842. }
  843. if (session->send_param.file_desc)
  844. {
  845. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  846. {
  847. struct fnet_fs_dirent dirent;
  848. fnet_fs_finfo(session->send_param.file_desc, &dirent);
  849. session->response.content_length = (long)dirent.d_size;
  850. }
  851. #endif
  852. result = FNET_OK;
  853. }
  854. else
  855. {
  856. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  857. session->response.status.code = FNET_HTTP_STATUS_CODE_NOT_FOUND;
  858. #endif
  859. result = FNET_ERR;
  860. }
  861. return result;
  862. }
  863. /************************************************************************
  864. * NAME: fnet_http_default_send
  865. *
  866. * DESCRIPTION:
  867. ************************************************************************/
  868. unsigned long fnet_http_default_send (struct fnet_http_if * http)
  869. {
  870. struct fnet_http_session_if *session = http->session_active;
  871. return fnet_fs_fread(session->buffer, sizeof(session->buffer), session->send_param.file_desc);
  872. }
  873. /************************************************************************
  874. * NAME: fnet_http_default_close
  875. *
  876. * DESCRIPTION:
  877. ************************************************************************/
  878. void fnet_http_default_close (struct fnet_http_if * http)
  879. {
  880. struct fnet_http_session_if *session = http->session_active;
  881. if(session->send_param.file_desc != http->index_file)
  882. fnet_fs_fclose(session->send_param.file_desc); /* Close file */
  883. }
  884. /************************************************************************
  885. * NAME: fnet_http_query_unencode
  886. *
  887. * DESCRIPTION:
  888. ************************************************************************/
  889. void fnet_http_query_unencode(char * dest, char * src)
  890. {
  891. if(dest && src)
  892. {
  893. for(; *src != 0; src++, dest++)
  894. if(*src == '+')
  895. *dest = ' ';
  896. else if(*src == '%')
  897. {
  898. int i;
  899. char val = 0;
  900. for(i=0; (i<2) && (*src != 0) ; i++)
  901. {
  902. src++;
  903. if((*src >= '0') && (*src <= '9'))
  904. {
  905. val = (char)((val << 4) + (*src - '0'));
  906. continue;
  907. }
  908. else if(((*src >= 'a') && (*src <= 'f')) || ((*src >= 'A') && (*src <= 'F')))
  909. {
  910. val = (char)((val << 4) + (*src + 10 - (((*src >= 'a') && (*src <= 'f')) ? 'a' : 'A')));
  911. continue;
  912. }
  913. break;
  914. }
  915. if(i==2)
  916. *dest = val;
  917. else
  918. *dest = '?';
  919. }
  920. else
  921. *dest = *src;
  922. *dest = '\0';
  923. }
  924. }
  925. /************************************************************************
  926. * NAME: fnet_http_uri_parse
  927. *
  928. * DESCRIPTION:
  929. * Returns pointer to the end of URI str.
  930. ************************************************************************/
  931. char *fnet_http_uri_parse(char * in_str, struct fnet_http_uri * uri)
  932. {
  933. char * cur = in_str;
  934. /* rel_uri = [ path ] [ "?" query ]*/
  935. if(cur && uri)
  936. {
  937. /*Parse the Request-URI. */
  938. /*Extract file name. */
  939. /* Ignore any initial spaces */
  940. while (*cur == ' ')
  941. cur++;
  942. uri->path = cur;
  943. uri->query = 0;
  944. uri->extension = 0;
  945. /* Find end of the file name. */
  946. while( *cur != '\0')
  947. {
  948. if (*cur == ' ') /* Path end is found */
  949. {
  950. *cur = '\0'; /* Mark path end */
  951. break;
  952. }
  953. else if(*cur == '?') /* Query is found */
  954. {
  955. char *end_query;
  956. *cur = '\0'; /* Mark path end */
  957. uri->query = cur + 1; /* Point to the next symbol after '?' */
  958. /* Find end of query.*/
  959. end_query = fnet_strchr( uri->query, ' ');
  960. if(end_query)
  961. {
  962. *end_query = '\0'; /* Mark query end */
  963. cur = end_query;
  964. break;
  965. }
  966. }
  967. cur ++;
  968. }
  969. uri->extension = fnet_strrchr(uri->path, '.'); /* Find file extension. */
  970. if( uri->query == 0) /* No query.*/
  971. uri->query = cur; /* Point to the blank string. */
  972. if( uri->extension == 0) /* No extension.*/
  973. uri->extension = cur; /* Point to the blank string. */
  974. else
  975. uri->extension ++; /* Skip the point character. */
  976. }
  977. return cur;
  978. }
  979. #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
  980. /************************************************************************
  981. * NAME: fnet_http_version_parse
  982. *
  983. * DESCRIPTION:
  984. ************************************************************************/
  985. static void fnet_http_version_parse(char * in_str, struct fnet_http_version * version)
  986. {
  987. char *cur = in_str;
  988. char *ptr;
  989. char *point_ptr;
  990. /* rel_uri = [ path ] [ "?" query ]*/
  991. if(cur && version)
  992. {
  993. /* Ignore any initial spaces */
  994. while (*cur == ' ')
  995. cur++;
  996. /* Find "HTTP/"*/
  997. if((cur = fnet_strstr( cur, FNET_HTTP_VERSION_HEADER )) !=0)
  998. {
  999. cur += sizeof(FNET_HTTP_VERSION_HEADER)-1;
  1000. /* Find '.'*/
  1001. if((point_ptr = fnet_strchr(cur, '.')) != 0)
  1002. {
  1003. *point_ptr = 0; /* Split numbers.*/
  1004. /*Major number*/
  1005. version->major = (char)fnet_strtoul (cur, &ptr, 10);
  1006. if (!((version->major == 0) && (ptr == cur)))
  1007. {
  1008. cur = point_ptr + 1;
  1009. /* Minor number.*/
  1010. version->minor = (char)fnet_strtoul (cur, &ptr, 10);
  1011. if (!((version->minor == 0) && (ptr == cur)))
  1012. goto EXIT; /* Exit.*/
  1013. }
  1014. }
  1015. }
  1016. /* No version info found.*/
  1017. version->major = 0;
  1018. version->minor = 9;
  1019. }
  1020. EXIT:
  1021. return;
  1022. }
  1023. /************************************************************************
  1024. * NAME: fnet_http_status_ok
  1025. *
  1026. * DESCRIPTION:
  1027. ************************************************************************/
  1028. static int fnet_http_status_ok(int status)
  1029. {
  1030. int result;
  1031. if((status == FNET_OK) || ((status/100) == 2) /* Successful 2xx. */)
  1032. result = FNET_OK;
  1033. else
  1034. result = FNET_ERR;
  1035. return result;
  1036. }
  1037. #endif /* FNET_CFG_HTTP_VERSION_MAJOR */
  1038. #endif