123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /*
- * Copyright (C) 2009-2015 Mamadou DIOP.
- *
- * This file is part of Open Source Doubango Framework.
- *
- * DOUBANGO is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * DOUBANGO is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with DOUBANGO.
- *
- */
- /**@file tmsrp_machine_message.rl
- * @brief Ragel file.
- */
- #include "tinymsrp/parsers/tmsrp_parser_message.h"
- #include "tinymsrp/headers/tmsrp_header_Dummy.h"
- #include "tinymsrp/headers/tmsrp_header_Expires.h"
- #include "tinymsrp/headers/tmsrp_header_Max-Expires.h"
- #include "tinymsrp/headers/tmsrp_header_Min-Expires.h"
- #include "tinymsrp/headers/tmsrp_header_Use-Path.h"
- #include "tinymsrp/headers/tmsrp_header_WWW-Authenticate.h"
- #include "tsk_string.h"
- #include "tsk_memory.h"
- #include "tsk_debug.h"
- 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);
- static void set_payload(tmsrp_message_t* msrp_msg, const void* ptr, tsk_size_t len);
- #define TMSRP_MSG_PARSER_ADD_HEADER(name) \
- if((header = (tmsrp_header_t*)tmsrp_header_##name##_parse(tag_start, (p - tag_start)))){ \
- tmsrp_message_add_header(msrp_msg, header); \
- header = tsk_object_unref(header); \
- }
- %%{
- machine tmsrp_machine_message;
-
- ###########################################
- # Includes
- ###########################################
- include tmsrp_machine_utils "./ragel/tmsrp_machine_utils.rl";
-
- action tag{
- tag_start = p;
- }
- ###########################################
- # Actions
- ###########################################
- action parse_Authentication_Info{
- //FIXME: TMSRP_MSG_PARSER_ADD_HEADER(Authentication_Info);
- TSK_DEBUG_WARN("Authentication_Info Not implemented");
- }
-
- action parse_Authorization{
- //FIXME: TMSRP_MSG_PARSER_ADD_HEADER(Authorization);
- TSK_DEBUG_WARN("Authorization Not implemented");
- }
-
- action parse_Byte_Range{
- TMSRP_MSG_PARSER_ADD_HEADER(Byte_Range);
- }
-
- action parse_Content_Type{
- TMSRP_MSG_PARSER_ADD_HEADER(Content_Type);
- }
-
- action parse_Expires{
- TMSRP_MSG_PARSER_ADD_HEADER(Expires);
- }
-
- action parse_Failure_Report{
- TMSRP_MSG_PARSER_ADD_HEADER(Failure_Report);
- }
-
- action parse_From_Path{
- TMSRP_MSG_PARSER_ADD_HEADER(From_Path);
- }
-
- action parse_Max_Expires{
- TMSRP_MSG_PARSER_ADD_HEADER(Max_Expires);
- }
-
- action parse_Message_ID{
- TMSRP_MSG_PARSER_ADD_HEADER(Message_ID);
- }
-
- action parse_Min_Expires{
- TMSRP_MSG_PARSER_ADD_HEADER(Min_Expires);
- }
-
- action parse_Status{
- TMSRP_MSG_PARSER_ADD_HEADER(Status);
- }
-
- action parse_Success_Report{
- TMSRP_MSG_PARSER_ADD_HEADER(Success_Report);
- }
-
- action parse_To_Path{
- TMSRP_MSG_PARSER_ADD_HEADER(To_Path);
- }
-
- action parse_Use_Path{
- TMSRP_MSG_PARSER_ADD_HEADER(Use_Path);
- }
-
- action parse_WWW_Authenticate{
- TMSRP_MSG_PARSER_ADD_HEADER(WWW_Authenticate);
- }
-
- action parse_Dummy{
- TMSRP_MSG_PARSER_ADD_HEADER(Dummy);
- }
-
- action parse_tid{
- TSK_PARSER_SET_STRING(msrp_msg->tid);
- }
- action parse_method{
- if(msrp_msg->type == tmsrp_unknown){
- msrp_msg->type = tmsrp_request;
- TSK_PARSER_SET_STRING(msrp_msg->line.request.method);
- msrp_msg->line.request.type = tmsrp_request_get_type(msrp_msg->line.request.method);
- }
- else{
- //cs = %%{ write first_final; }%%;
- cs = tmsrp_machine_message_error;
- TSK_DEBUG_ERROR("Message type already defined.");
- }
- }
- action parse_status_code{
- if(msrp_msg->type == tmsrp_unknown){
- msrp_msg->type = tmsrp_response;
- TSK_PARSER_SET_INT(msrp_msg->line.response.status);
- }
- else{
- //cs = %%{ write first_final; }%%;
- cs = tmsrp_machine_message_error;
- TSK_DEBUG_ERROR("Message type already defined.");
- }
- }
- action parse_comment{
- TSK_PARSER_SET_STRING(msrp_msg->line.response.comment);
- }
-
- action try_parse_data{
- parse_payload(msrp_msg, tag_start, &p, pe, &payload_parsed); // will update "p"
- }
- action parse_data{
- // if the msrp message contain a valid content-type, then gob it otherwise continue until we reach the endline
- int len;
- if(parse_payload(msrp_msg, tag_start, &p, pe, &payload_parsed)){ // will update "p"
- // (This space left deliberately blank)
- }
- else if((len = (int)(p - tag_start))>0){
- set_payload(msrp_msg, tag_start, (tsk_size_t)len);
- }
- }
- action parse_endtid{
- TSK_PARSER_SET_STRING(msrp_msg->end_line.tid);
- }
- action parse_cflag{
- if(tag_start){
- msrp_msg->end_line.cflag = *tag_start;
- }
- else msrp_msg->end_line.cflag = '#';
- }
- action outside_endline{
- *msg_size = (p - (const char*)input) + 1;
- }
-
- action into_endline{
- into_endline = tsk_true;
- }
- action endtid_match{
- ( into_endline || (((pe-p) >7/*seven hyphens*/) && (msrp_msg->tid) && tsk_strniequals(msrp_msg->tid, (p+7), tsk_strlen(msrp_msg->tid))) )
- }
- ###########################################
- # Headers
- ###########################################
- Authentication_Info = "Authentication-Info:"i SP any* :>CRLF %parse_Authentication_Info;
- Authorization = "Authorization:"i SP any* :>CRLF %parse_Authorization;
- Byte_Range = "Byte-Range:"i SP any* :>CRLF %parse_Byte_Range;
- Content_Type = "Content-Type:"i SP any* :>CRLF %parse_Content_Type;
- Expires = "Expires:"i SP any* :>CRLF %parse_Expires;
- Failure_Report = "Failure-Report:"i SP any* :>CRLF %parse_Failure_Report ;
- From_Path = "From-Path:"i SP any* :>CRLF %parse_From_Path ;
- Max_Expires = "Max-Expires:"i SP any* :>CRLF %parse_Max_Expires;
- Message_ID = "Message-ID:"i SP any* :>CRLF %parse_Message_ID;
- Min_Expires = "Min-Expires:"i SP any* :>CRLF %parse_Min_Expires;
- Status = "Status:"i SP any* :>CRLF %parse_Status;
- Success_Report = "Success-Report:"i SP any* :>CRLF %parse_Success_Report;
- To_Path = "To-Path:"i SP any* :>CRLF %parse_To_Path;
- Use_Path = "Use-Path:"i SP any* :>CRLF %parse_Use_Path;
- WWW_Authenticate = "WWW-Authenticate:"i SP any* :>CRLF %parse_WWW_Authenticate;
-
- Dummy = hname ":" SP hval :>CRLF %parse_Dummy;
-
- 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;
- #headers = To_Path From_Path ( header )*;
- headers = ( header )*;
- ###########################################
- # Utils
- ###########################################
- transact_id = ident;
- method = UPALPHA*;
- status_code = DIGIT{3};
- comment = utf8text;
-
- continuation_flag = "+" | "$" | "#";
- end_line = "-------" transact_id>tag %parse_endtid continuation_flag>tag %parse_cflag CRLF;
- Other_Mime_header = Dummy;
- data = any*;
- ###########################################
- # Request
- ###########################################
- req_start = "MSRP" SP transact_id>tag %parse_tid SP method>tag %parse_method CRLF;
- #content_stuff = (Other_Mime_header)* CRLF data>tag %parse_data :>CRLF;
- content_stuff = data>tag >try_parse_data %parse_data;
- msrp_request = req_start headers>10 (CRLF content_stuff CRLF)?>5 :>end_line when endtid_match >into_endline;
- ###########################################
- # Response
- ###########################################
- resp_start = "MSRP" SP transact_id>tag %parse_tid SP status_code>tag %parse_status_code (SP comment>tag %parse_comment)? CRLF;
- msrp_response = resp_start headers end_line;
- ###########################################
- # Message
- ###########################################
- msrp_req_or_resp = (msrp_request | msrp_response)>1 @outside_endline any*>0;
- ###########################################
- # Entry Point
- ###########################################
- main := msrp_req_or_resp;
- }%%
- TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
- /* Ragel data */
- %% write data;
- TSK_RAGEL_DISABLE_WARNINGS_END()
- tmsrp_message_t* tmsrp_message_parse(const void *input, tsk_size_t size)
- {
- tsk_size_t msg_size;
- return tmsrp_message_parse_2(input, size, &msg_size);
- }
- tmsrp_message_t* tmsrp_message_parse_2(const void *input, tsk_size_t size, tsk_size_t* msg_size)
- {
- tmsrp_message_t* msrp_msg = tsk_null;
- const char* tag_start = tsk_null;
- tmsrp_header_t* header = tsk_null;
- tsk_bool_t into_endline = tsk_false;
- tsk_bool_t payload_parsed = tsk_false;
-
- /* Ragel variables */
- int cs = 0;
- const char* p = input;
- const char* pe = p + size;
- const char* eof = tsk_null;
- (void)(eof);
- (void)(tmsrp_machine_message_first_final);
- (void)(tmsrp_machine_message_error);
- (void)(tmsrp_machine_message_en_main);
- *msg_size = 0;
- if(!input || !size){
- //TSK_DEBUG_ERROR("Null or empty buffer."); // --> very common case(stream): do not bother us...
- goto bail;
- }
- if(!(msrp_msg = tmsrp_message_create_null())){
- goto bail;
- }
- TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
- /* Ragel init */
- %% write init;
- /* Ragel execute */
- %% write exec;
- TSK_RAGEL_DISABLE_WARNINGS_END()
- /* Check result */
- if( cs < %%{ write first_final; }%% ){
- //TSK_DEBUG_ERROR("Failed to parse MSRP message."); --> very common case(stream): do not bother us...
- TSK_OBJECT_SAFE_FREE(msrp_msg);
- goto bail;
- }
-
- bail:
- return msrp_msg;
- }
- 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)
- {
- int64_t payload_len, endline_len;
- tsk_bool_t can_parse_payload;
- if(*payload_parsed){
- TSK_DEBUG_INFO("payload already parsed");
- return tsk_true;
- }
- if(pe && p && *p && msrp_msg && (can_parse_payload = TMSRP_HEADER_BYTE_RANGE_IS_VALID(msrp_msg->ByteRange))){
- payload_len = (msrp_msg->ByteRange->end - msrp_msg->ByteRange->start) + 1;
- endline_len = 2/*CRLF*/ + 7/*hyphens*/ + tsk_strlen(msrp_msg->tid) + 2/*CRLF*/;
- can_parse_payload = (pe - tag_start) > (payload_len + endline_len);
- if(can_parse_payload){
- set_payload(msrp_msg, tag_start, (tsk_size_t)payload_len);
- *p = ((tag_start + payload_len) - 1);
- *payload_parsed = tsk_true;
- return tsk_true;
- }
- }
- return tsk_false;
- }
- static void set_payload(tmsrp_message_t* msrp_msg, const void* ptr, tsk_size_t len)
- {
- if(msrp_msg->Content){
- tsk_buffer_cleanup(msrp_msg->Content);
- tsk_buffer_append(msrp_msg->Content, ptr, len);
- }
- else{
- msrp_msg->Content = tsk_buffer_create(ptr, len);
- }
- }
|