thttp_parser_message.rl 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright (C) 2010-2015 Mamadou Diop.
  3. *
  4. * This file is part of Open Source Doubango Framework.
  5. *
  6. * DOUBANGO is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * DOUBANGO is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with DOUBANGO.
  18. *
  19. */
  20. /**@file thttp_parser_message.c
  21. * @brief HTTP parser.
  22. *
  23. */
  24. #include "tinyhttp/parsers/thttp_parser_message.h"
  25. #include "tinyhttp/parsers/thttp_parser_header.h"
  26. #include "tinyhttp/parsers/thttp_parser_url.h"
  27. #include "tsk_debug.h"
  28. #include "tsk_memory.h"
  29. static void thttp_message_parser_execute(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content);
  30. static void thttp_message_parser_init(tsk_ragel_state_t *state);
  31. static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content);
  32. /***********************************
  33. * Ragel state machine.
  34. */
  35. %%{
  36. machine thttp_machine_parser_message;
  37. #/* Tag the buffer (start point). */
  38. action tag{
  39. state->tag_start = p;
  40. }
  41. #/* HTTP method */
  42. action parse_method{
  43. int len;
  44. state->tag_end = p;
  45. len = (int)(state->tag_end - state->tag_start);
  46. if(message->type == thttp_unknown){
  47. message->type = thttp_request;
  48. if(!message->line.request.method){
  49. message->line.request.method = tsk_calloc(1, len+1);
  50. memcpy(message->line.request.method, state->tag_start, len);
  51. }
  52. }
  53. else{
  54. state->cs = thttp_machine_parser_message_error;
  55. }
  56. }
  57. #/* Request URI parsing */
  58. action parse_requesturl{
  59. int len;
  60. state->tag_end = p;
  61. len = (int)(state->tag_end - state->tag_start);
  62. if(!message->line.request.url){
  63. message->line.request.url = thttp_url_parse(state->tag_start, (tsk_size_t)len);
  64. }
  65. }
  66. #/* Sip Version */
  67. action parse_httpversion{
  68. int len;
  69. state->tag_end = p;
  70. len = (int)(state->tag_end - state->tag_start);
  71. if(!message->http_version){
  72. message->http_version = tsk_calloc(1, len+1);
  73. memcpy(message->http_version, state->tag_start, len);
  74. }
  75. }
  76. #/* Status Code */
  77. action parse_status_code{
  78. int len;
  79. state->tag_end = p;
  80. len = (int)(state->tag_end - state->tag_start);
  81. if(message->type == thttp_unknown){
  82. message->type = thttp_response;
  83. message->line.response.status_code = atoi(state->tag_start);
  84. }
  85. else{
  86. state->cs = thttp_machine_parser_message_error;
  87. }
  88. }
  89. #/* Reason Phrase */
  90. action parse_reason_phrase{
  91. int len;
  92. state->tag_end = p;
  93. len = (int)(state->tag_end - state->tag_start);
  94. if(!message->line.response.reason_phrase){
  95. message->line.response.reason_phrase = tsk_calloc(1, len+1);
  96. memcpy(message->line.response.reason_phrase, state->tag_start, len);
  97. }
  98. }
  99. #/* Parse http header */
  100. action parse_header{
  101. int len;
  102. state->tag_end = p;
  103. len = (int)(state->tag_end - state->tag_start);
  104. if(thttp_header_parse(state, message)){
  105. TSK_DEBUG_ERROR("Failed to parse header - %s", state->tag_start);
  106. }
  107. else{
  108. //TSK_DEBUG_INFO("THTTP_MESSAGE_PARSER::PARSE_HEADER len=%d state=%d", len, state->cs);
  109. }
  110. }
  111. #/* Parse http content/body. */
  112. #action parse_body
  113. #{
  114. # int len;
  115. # state->tag_end = p;
  116. # len = (int)(state->tag_end - state->tag_start);
  117. # TSK_DEBUG_ERROR("==THTTP_MESSAGE_PARSER::PARSE_BODY==");
  118. #}
  119. #/* End-Of-Headers */
  120. action eoh{
  121. state->cs = cs;
  122. state->p = p;
  123. state->pe = pe;
  124. state->eof = eof;
  125. thttp_message_parser_eoh(state, message, extract_content);
  126. cs = state->cs;
  127. p = state->p;
  128. pe = state->pe;
  129. eof = state->eof;
  130. }
  131. # Includes
  132. include thttp_machine_utils "./ragel/thttp_machine_utils.rl";
  133. include thttp_machine_message "./ragel/thttp_machine_message.rl";
  134. # Entry point
  135. main := HTTP_message;
  136. }%%
  137. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  138. /* Regel data */
  139. %%write data;
  140. TSK_RAGEL_DISABLE_WARNINGS_END()
  141. /** Parses raw HTTP buffer.
  142. *
  143. * @param state Ragel state containing the buffer references.
  144. * @param result @ref thttp_message_t object representing the raw buffer.
  145. * @param extract_content Indicates wheteher to parse the message content or not. If set to true, then
  146. * only headers will be parsed.
  147. *
  148. * @retval Zero if succeed and non-zero error code otherwise.
  149. **/
  150. int thttp_message_parse(tsk_ragel_state_t *state, thttp_message_t **result, tsk_bool_t extract_content)
  151. {
  152. if(!state || state->pe <= state->p){
  153. return -1;
  154. }
  155. if(!*result){
  156. *result = thttp_message_create();
  157. }
  158. /* Ragel init */
  159. thttp_message_parser_init(state);
  160. /*
  161. * State mechine execution.
  162. */
  163. thttp_message_parser_execute(state, *result, extract_content);
  164. /* Check result */
  165. if( state->cs < %%{ write first_final; }%% ){
  166. TSK_DEBUG_ERROR("Failed to parse HTTP message.");
  167. TSK_OBJECT_SAFE_FREE(*result);
  168. return -2;
  169. }
  170. return 0;
  171. }
  172. static void thttp_message_parser_init(tsk_ragel_state_t *state)
  173. {
  174. int cs = 0;
  175. /* Regel machine initialization. */
  176. %% write init;
  177. state->cs = cs;
  178. }
  179. static void thttp_message_parser_execute(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content)
  180. {
  181. int cs = state->cs;
  182. const char *p = state->p;
  183. const char *pe = state->pe;
  184. const char *eof = state->eof;
  185. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  186. %% write exec;
  187. TSK_RAGEL_DISABLE_WARNINGS_END()
  188. state->cs = cs;
  189. state->p = p;
  190. state->pe = pe;
  191. state->eof = eof;
  192. }
  193. static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content)
  194. {
  195. int cs = state->cs;
  196. const char *p = state->p;
  197. const char *pe = state->pe;
  198. const char *eof = state->eof;
  199. if(extract_content && message){
  200. uint32_t clen = THTTP_MESSAGE_CONTENT_LENGTH(message);
  201. if(clen){
  202. if((p + clen)<pe && !message->Content){
  203. message->Content = tsk_buffer_create((p+1), clen);
  204. p = (p + clen);
  205. }
  206. else{
  207. p = (pe - 1);
  208. }
  209. }
  210. }
  211. //%%write eof;
  212. state->cs = cs;
  213. state->p = p;
  214. state->pe = pe;
  215. state->eof = eof;
  216. }