tmsrp_parser_message.rl 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright (C) 2009-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 tmsrp_machine_message.rl
  21. * @brief Ragel file.
  22. */
  23. #include "tinymsrp/parsers/tmsrp_parser_message.h"
  24. #include "tinymsrp/headers/tmsrp_header_Dummy.h"
  25. #include "tinymsrp/headers/tmsrp_header_Expires.h"
  26. #include "tinymsrp/headers/tmsrp_header_Max-Expires.h"
  27. #include "tinymsrp/headers/tmsrp_header_Min-Expires.h"
  28. #include "tinymsrp/headers/tmsrp_header_Use-Path.h"
  29. #include "tinymsrp/headers/tmsrp_header_WWW-Authenticate.h"
  30. #include "tsk_string.h"
  31. #include "tsk_memory.h"
  32. #include "tsk_debug.h"
  33. static tsk_bool_t parse_payload(tmsrp_message_t* msrp_msg, const char* tag_start, const char** p, const char* pe, tsk_bool_t* payload_parsed);
  34. static void set_payload(tmsrp_message_t* msrp_msg, const void* ptr, tsk_size_t len);
  35. #define TMSRP_MSG_PARSER_ADD_HEADER(name) \
  36. if((header = (tmsrp_header_t*)tmsrp_header_##name##_parse(tag_start, (p - tag_start)))){ \
  37. tmsrp_message_add_header(msrp_msg, header); \
  38. header = tsk_object_unref(header); \
  39. }
  40. %%{
  41. machine tmsrp_machine_message;
  42. ###########################################
  43. # Includes
  44. ###########################################
  45. include tmsrp_machine_utils "./ragel/tmsrp_machine_utils.rl";
  46. action tag{
  47. tag_start = p;
  48. }
  49. ###########################################
  50. # Actions
  51. ###########################################
  52. action parse_Authentication_Info{
  53. //FIXME: TMSRP_MSG_PARSER_ADD_HEADER(Authentication_Info);
  54. TSK_DEBUG_WARN("Authentication_Info Not implemented");
  55. }
  56. action parse_Authorization{
  57. //FIXME: TMSRP_MSG_PARSER_ADD_HEADER(Authorization);
  58. TSK_DEBUG_WARN("Authorization Not implemented");
  59. }
  60. action parse_Byte_Range{
  61. TMSRP_MSG_PARSER_ADD_HEADER(Byte_Range);
  62. }
  63. action parse_Content_Type{
  64. TMSRP_MSG_PARSER_ADD_HEADER(Content_Type);
  65. }
  66. action parse_Expires{
  67. TMSRP_MSG_PARSER_ADD_HEADER(Expires);
  68. }
  69. action parse_Failure_Report{
  70. TMSRP_MSG_PARSER_ADD_HEADER(Failure_Report);
  71. }
  72. action parse_From_Path{
  73. TMSRP_MSG_PARSER_ADD_HEADER(From_Path);
  74. }
  75. action parse_Max_Expires{
  76. TMSRP_MSG_PARSER_ADD_HEADER(Max_Expires);
  77. }
  78. action parse_Message_ID{
  79. TMSRP_MSG_PARSER_ADD_HEADER(Message_ID);
  80. }
  81. action parse_Min_Expires{
  82. TMSRP_MSG_PARSER_ADD_HEADER(Min_Expires);
  83. }
  84. action parse_Status{
  85. TMSRP_MSG_PARSER_ADD_HEADER(Status);
  86. }
  87. action parse_Success_Report{
  88. TMSRP_MSG_PARSER_ADD_HEADER(Success_Report);
  89. }
  90. action parse_To_Path{
  91. TMSRP_MSG_PARSER_ADD_HEADER(To_Path);
  92. }
  93. action parse_Use_Path{
  94. TMSRP_MSG_PARSER_ADD_HEADER(Use_Path);
  95. }
  96. action parse_WWW_Authenticate{
  97. TMSRP_MSG_PARSER_ADD_HEADER(WWW_Authenticate);
  98. }
  99. action parse_Dummy{
  100. TMSRP_MSG_PARSER_ADD_HEADER(Dummy);
  101. }
  102. action parse_tid{
  103. TSK_PARSER_SET_STRING(msrp_msg->tid);
  104. }
  105. action parse_method{
  106. if(msrp_msg->type == tmsrp_unknown){
  107. msrp_msg->type = tmsrp_request;
  108. TSK_PARSER_SET_STRING(msrp_msg->line.request.method);
  109. msrp_msg->line.request.type = tmsrp_request_get_type(msrp_msg->line.request.method);
  110. }
  111. else{
  112. //cs = %%{ write first_final; }%%;
  113. cs = tmsrp_machine_message_error;
  114. TSK_DEBUG_ERROR("Message type already defined.");
  115. }
  116. }
  117. action parse_status_code{
  118. if(msrp_msg->type == tmsrp_unknown){
  119. msrp_msg->type = tmsrp_response;
  120. TSK_PARSER_SET_INT(msrp_msg->line.response.status);
  121. }
  122. else{
  123. //cs = %%{ write first_final; }%%;
  124. cs = tmsrp_machine_message_error;
  125. TSK_DEBUG_ERROR("Message type already defined.");
  126. }
  127. }
  128. action parse_comment{
  129. TSK_PARSER_SET_STRING(msrp_msg->line.response.comment);
  130. }
  131. action try_parse_data{
  132. parse_payload(msrp_msg, tag_start, &p, pe, &payload_parsed); // will update "p"
  133. }
  134. action parse_data{
  135. // if the msrp message contain a valid content-type, then gob it otherwise continue until we reach the endline
  136. int len;
  137. if(parse_payload(msrp_msg, tag_start, &p, pe, &payload_parsed)){ // will update "p"
  138. // (This space left deliberately blank)
  139. }
  140. else if((len = (int)(p - tag_start))>0){
  141. set_payload(msrp_msg, tag_start, (tsk_size_t)len);
  142. }
  143. }
  144. action parse_endtid{
  145. TSK_PARSER_SET_STRING(msrp_msg->end_line.tid);
  146. }
  147. action parse_cflag{
  148. if(tag_start){
  149. msrp_msg->end_line.cflag = *tag_start;
  150. }
  151. else msrp_msg->end_line.cflag = '#';
  152. }
  153. action outside_endline{
  154. *msg_size = (p - (const char*)input) + 1;
  155. }
  156. action into_endline{
  157. into_endline = tsk_true;
  158. }
  159. action endtid_match{
  160. ( into_endline || (((pe-p) >7/*seven hyphens*/) && (msrp_msg->tid) && tsk_strniequals(msrp_msg->tid, (p+7), tsk_strlen(msrp_msg->tid))) )
  161. }
  162. ###########################################
  163. # Headers
  164. ###########################################
  165. Authentication_Info = "Authentication-Info:"i SP any* :>CRLF %parse_Authentication_Info;
  166. Authorization = "Authorization:"i SP any* :>CRLF %parse_Authorization;
  167. Byte_Range = "Byte-Range:"i SP any* :>CRLF %parse_Byte_Range;
  168. Content_Type = "Content-Type:"i SP any* :>CRLF %parse_Content_Type;
  169. Expires = "Expires:"i SP any* :>CRLF %parse_Expires;
  170. Failure_Report = "Failure-Report:"i SP any* :>CRLF %parse_Failure_Report ;
  171. From_Path = "From-Path:"i SP any* :>CRLF %parse_From_Path ;
  172. Max_Expires = "Max-Expires:"i SP any* :>CRLF %parse_Max_Expires;
  173. Message_ID = "Message-ID:"i SP any* :>CRLF %parse_Message_ID;
  174. Min_Expires = "Min-Expires:"i SP any* :>CRLF %parse_Min_Expires;
  175. Status = "Status:"i SP any* :>CRLF %parse_Status;
  176. Success_Report = "Success-Report:"i SP any* :>CRLF %parse_Success_Report;
  177. To_Path = "To-Path:"i SP any* :>CRLF %parse_To_Path;
  178. Use_Path = "Use-Path:"i SP any* :>CRLF %parse_Use_Path;
  179. WWW_Authenticate = "WWW-Authenticate:"i SP any* :>CRLF %parse_WWW_Authenticate;
  180. Dummy = hname ":" SP hval :>CRLF %parse_Dummy;
  181. header = (Authentication_Info | Authorization | Byte_Range | Content_Type | Expires | Failure_Report | From_Path | Max_Expires | Message_ID | Min_Expires | Status | Success_Report | To_Path | Use_Path | WWW_Authenticate)>tag @10 | (Dummy>tag) @0;
  182. #headers = To_Path From_Path ( header )*;
  183. headers = ( header )*;
  184. ###########################################
  185. # Utils
  186. ###########################################
  187. transact_id = ident;
  188. method = UPALPHA*;
  189. status_code = DIGIT{3};
  190. comment = utf8text;
  191. continuation_flag = "+" | "$" | "#";
  192. end_line = "-------" transact_id>tag %parse_endtid continuation_flag>tag %parse_cflag CRLF;
  193. Other_Mime_header = Dummy;
  194. data = any*;
  195. ###########################################
  196. # Request
  197. ###########################################
  198. req_start = "MSRP" SP transact_id>tag %parse_tid SP method>tag %parse_method CRLF;
  199. #content_stuff = (Other_Mime_header)* CRLF data>tag %parse_data :>CRLF;
  200. content_stuff = data>tag >try_parse_data %parse_data;
  201. msrp_request = req_start headers>10 (CRLF content_stuff CRLF)?>5 :>end_line when endtid_match >into_endline;
  202. ###########################################
  203. # Response
  204. ###########################################
  205. resp_start = "MSRP" SP transact_id>tag %parse_tid SP status_code>tag %parse_status_code (SP comment>tag %parse_comment)? CRLF;
  206. msrp_response = resp_start headers end_line;
  207. ###########################################
  208. # Message
  209. ###########################################
  210. msrp_req_or_resp = (msrp_request | msrp_response)>1 @outside_endline any*>0;
  211. ###########################################
  212. # Entry Point
  213. ###########################################
  214. main := msrp_req_or_resp;
  215. }%%
  216. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  217. /* Ragel data */
  218. %% write data;
  219. TSK_RAGEL_DISABLE_WARNINGS_END()
  220. tmsrp_message_t* tmsrp_message_parse(const void *input, tsk_size_t size)
  221. {
  222. tsk_size_t msg_size;
  223. return tmsrp_message_parse_2(input, size, &msg_size);
  224. }
  225. tmsrp_message_t* tmsrp_message_parse_2(const void *input, tsk_size_t size, tsk_size_t* msg_size)
  226. {
  227. tmsrp_message_t* msrp_msg = tsk_null;
  228. const char* tag_start = tsk_null;
  229. tmsrp_header_t* header = tsk_null;
  230. tsk_bool_t into_endline = tsk_false;
  231. tsk_bool_t payload_parsed = tsk_false;
  232. /* Ragel variables */
  233. int cs = 0;
  234. const char* p = input;
  235. const char* pe = p + size;
  236. const char* eof = tsk_null;
  237. (void)(eof);
  238. (void)(tmsrp_machine_message_first_final);
  239. (void)(tmsrp_machine_message_error);
  240. (void)(tmsrp_machine_message_en_main);
  241. *msg_size = 0;
  242. if(!input || !size){
  243. //TSK_DEBUG_ERROR("Null or empty buffer."); // --> very common case(stream): do not bother us...
  244. goto bail;
  245. }
  246. if(!(msrp_msg = tmsrp_message_create_null())){
  247. goto bail;
  248. }
  249. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  250. /* Ragel init */
  251. %% write init;
  252. /* Ragel execute */
  253. %% write exec;
  254. TSK_RAGEL_DISABLE_WARNINGS_END()
  255. /* Check result */
  256. if( cs < %%{ write first_final; }%% ){
  257. //TSK_DEBUG_ERROR("Failed to parse MSRP message."); --> very common case(stream): do not bother us...
  258. TSK_OBJECT_SAFE_FREE(msrp_msg);
  259. goto bail;
  260. }
  261. bail:
  262. return msrp_msg;
  263. }
  264. static tsk_bool_t parse_payload(tmsrp_message_t* msrp_msg, const char* tag_start, const char** p, const char* pe, tsk_bool_t* payload_parsed)
  265. {
  266. int64_t payload_len, endline_len;
  267. tsk_bool_t can_parse_payload;
  268. if(*payload_parsed){
  269. TSK_DEBUG_INFO("payload already parsed");
  270. return tsk_true;
  271. }
  272. if(pe && p && *p && msrp_msg && (can_parse_payload = TMSRP_HEADER_BYTE_RANGE_IS_VALID(msrp_msg->ByteRange))){
  273. payload_len = (msrp_msg->ByteRange->end - msrp_msg->ByteRange->start) + 1;
  274. endline_len = 2/*CRLF*/ + 7/*hyphens*/ + tsk_strlen(msrp_msg->tid) + 2/*CRLF*/;
  275. can_parse_payload = (pe - tag_start) > (payload_len + endline_len);
  276. if(can_parse_payload){
  277. set_payload(msrp_msg, tag_start, (tsk_size_t)payload_len);
  278. *p = ((tag_start + payload_len) - 1);
  279. *payload_parsed = tsk_true;
  280. return tsk_true;
  281. }
  282. }
  283. return tsk_false;
  284. }
  285. static void set_payload(tmsrp_message_t* msrp_msg, const void* ptr, tsk_size_t len)
  286. {
  287. if(msrp_msg->Content){
  288. tsk_buffer_cleanup(msrp_msg->Content);
  289. tsk_buffer_append(msrp_msg->Content, ptr, len);
  290. }
  291. else{
  292. msrp_msg->Content = tsk_buffer_create(ptr, len);
  293. }
  294. }