diff options
author | Mamadou DIOP <bossiel@yahoo.fr> | 2015-08-17 01:56:35 +0200 |
---|---|---|
committer | Mamadou DIOP <bossiel@yahoo.fr> | 2015-08-17 01:56:35 +0200 |
commit | 631fffee8a28b1bec5ed1f1d26a20e0135967f99 (patch) | |
tree | 74afe3bf3efe15aa82bcd0272b2b0f4d48c2d837 /tinyMEDIA/ragel | |
parent | 7908865936604036e6f200f1b5e069f8752f3a3a (diff) | |
download | doubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.zip doubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.tar.gz |
-
Diffstat (limited to 'tinyMEDIA/ragel')
-rw-r--r-- | tinyMEDIA/ragel/tmedia_content_cpim.rl | 244 | ||||
-rw-r--r-- | tinyMEDIA/ragel/tmedia_imageattr.rl | 183 | ||||
-rw-r--r-- | tinyMEDIA/ragel/tmedia_machine_utils.rl | 78 |
3 files changed, 505 insertions, 0 deletions
diff --git a/tinyMEDIA/ragel/tmedia_content_cpim.rl b/tinyMEDIA/ragel/tmedia_content_cpim.rl new file mode 100644 index 0000000..eeecbd3 --- /dev/null +++ b/tinyMEDIA/ragel/tmedia_content_cpim.rl @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2010-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 tmedia_content_cpim.c + * @brief Common Presence and Instant Messaging (CPIM): Message Format (RFC 3862) + */ +#include "tinymedia/content/tmedia_content_cpim.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" +#include "tsk_string.h" +#include "tsk_ragel_state.h" + +#include <string.h> + +/* RFC 3862 - 2. Overall Message Structure +A complete message looks something like this: + + m: Content-type: Message/CPIM + s: + h: (message-metadata-headers) + s: + e: (encapsulated MIME message-body) + + The end of the message body is defined by the framing mechanism of + the protocol used. The tags 'm:', 's:', 'h:', 'e:', and 'x:' are not + part of the message format and are used here to indicate the + different parts of the message, thus: + + m: MIME headers for the overall message + s: a blank separator line + h: message headers + e: encapsulated MIME object containing the message content + x: MIME security multipart message wrapper +*/ + + + + + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine tmedia_machine_content_cpim; + + # Includes + include tmedia_machine_utils "./ragel/tmedia_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action is_parsing_mime_headers{ + parsing_mime_headers = tsk_true; + } + + action is_parsing_message_headers{ + parsing_mime_headers = tsk_false; + } + + action parse_hname{ + TSK_PARSER_SET_STRING(hname); + } + + action parse_hvalue{ + tmedia_content_header_t* header; + TSK_PARSER_SET_STRING(hvalue); + header = tmedia_content_header_create(hname, hvalue); + TSK_FREE(hname); TSK_FREE(hvalue); + + if(parsing_mime_headers){ + if(!TMEDIA_CONTENT_CPIM(self)->m_headers){ + TMEDIA_CONTENT_CPIM(self)->m_headers = tsk_list_create(); + } + tsk_list_push_back_data(TMEDIA_CONTENT_CPIM(self)->m_headers, (void**)&header); + } + else{ + if(!TMEDIA_CONTENT_CPIM(self)->h_headers){ + TMEDIA_CONTENT_CPIM(self)->h_headers = tsk_list_create(); + } + tsk_list_push_back_data(TMEDIA_CONTENT_CPIM(self)->h_headers, (void**)&header); + } + } + + action parse_e{ + int len = (int)(p - tag_start); + if(len && tag_start){ + if(TMEDIA_CONTENT_CPIM(self)->e){ + TSK_OBJECT_SAFE_FREE(TMEDIA_CONTENT_CPIM(self)->e); \ + } + TMEDIA_CONTENT_CPIM(self)->e = tsk_buffer_create(tag_start, len); + } + } + + hname = token>tag %parse_hname; + hvalue = any*>tag %parse_hvalue; + + Header = hname :>SP*:> ":" SP*<: hvalue :> CRLF; + m = Header+ >is_parsing_mime_headers; + s = CRLF; + h = Header+ >is_parsing_message_headers; + e = any*>tag %parse_e; + + # Entry point + main := m s h s e; +}%% + + +static int tmedia_content_cpim_parse(tmedia_content_t* self, const void* in_data, tsk_size_t in_size) +{ + int cs = 0; + const char *p = in_data; + const char *pe = p + in_size; + const char *eof = pe; + + const char *tag_start = tsk_null; + + char* hname = tsk_null; + char* hvalue = tsk_null; + tsk_bool_t parsing_mime_headers = tsk_true; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(tmedia_machine_content_cpim_first_final); + (void)(tmedia_machine_content_cpim_error); + (void)(tmedia_machine_content_cpim_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + TSK_FREE(hname); + TSK_FREE(hvalue); + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse CPIM content"); + return -1; + } + + return 0; +} + +static tsk_buffer_t* tmedia_content_cpim_get_data(tmedia_content_t* self) +{ + tsk_buffer_t* data = tsk_buffer_create_null(); + tmedia_content_cpim_t *cpim = TMEDIA_CONTENT_CPIM(self); + const tsk_list_item_t* item; + /* + m: Content-type: Message/CPIM + s: + h: (message-metadata-headers) + s: + e: (encapsulated MIME message-body) + x: MIME security multipart message wrapper + */ + if(cpim->m_headers){ + tsk_list_foreach(item, cpim->m_headers){ + char* hstring = tmedia_content_header_tostring(TMEDIA_CONTENT_HEADER(item->data)); + tsk_buffer_append_2(data, TSK_LIST_IS_LAST(cpim->m_headers, item) ? "%s\r\n\r\n" : "%s\r\n", hstring); + TSK_FREE(hstring); + } + } + if(cpim->h_headers){ + tsk_list_foreach(item, cpim->h_headers){ + char* hstring = tmedia_content_header_tostring(TMEDIA_CONTENT_HEADER(item->data)); + tsk_buffer_append_2(data, TSK_LIST_IS_LAST(cpim->h_headers, item) ? "%s\r\n\r\n" : "%s\r\n", hstring); + TSK_FREE(hstring); + } + } + if(cpim->e){ + tsk_buffer_append(data, TSK_BUFFER_DATA(cpim->e), TSK_BUFFER_SIZE(cpim->e)); + } + if(cpim->x){ + tsk_buffer_append(data, TSK_BUFFER_DATA(cpim->x), TSK_BUFFER_SIZE(cpim->x)); + } + + return data; +} + +//================================================================================================= +// object/plugin definitions +// +/* constructor */ +static tsk_object_t* tmedia_content_cpim_ctor(tsk_object_t * self, va_list * app) +{ + tmedia_content_cpim_t *cpim = self; + if(cpim){ + /* init base: called by tmedia_content_create() */ + /* init self */ + } + return self; +} +/* destructor */ +static tsk_object_t* tmedia_content_cpim_dtor(tsk_object_t * self) +{ + tmedia_content_cpim_t *cpim = self; + if(cpim){ + /* deinit base */ + tmedia_content_deinit(TMEDIA_CONTENT(cpim)); + /* deinit self */ + TSK_OBJECT_SAFE_FREE(cpim->m_headers); + TSK_OBJECT_SAFE_FREE(cpim->h_headers); + TSK_OBJECT_SAFE_FREE(cpim->e); + TSK_OBJECT_SAFE_FREE(cpim->x); + } + + return self; +} +/* object definition */ +static const tsk_object_def_t tmedia_content_cpim_def_s = +{ + sizeof(tmedia_content_cpim_t), + tmedia_content_cpim_ctor, + tmedia_content_cpim_dtor, + tsk_null, +}; +/* plugin definition*/ +static const tmedia_content_plugin_def_t tmedia_content_cpim_plugin_def_s = +{ + &tmedia_content_cpim_def_s, + + TMEDIA_CONTENT_CPIM_TYPE, + tmedia_content_cpim_parse, + tmedia_content_cpim_get_data +}; +const tmedia_content_plugin_def_t *tmedia_content_cpim_plugin_def_t = &tmedia_content_cpim_plugin_def_s;
\ No newline at end of file diff --git a/tinyMEDIA/ragel/tmedia_imageattr.rl b/tinyMEDIA/ragel/tmedia_imageattr.rl new file mode 100644 index 0000000..40ad8c8 --- /dev/null +++ b/tinyMEDIA/ragel/tmedia_imageattr.rl @@ -0,0 +1,183 @@ +/* +* Copyright (C) 2012-2015 Doubango Telecom <http://www.doubango.org> +* +* 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 tmedia_imageattr.c + * @brief 'image-attr' parser as per RFC 6236 + */ +#include "tinymedia/tmedia_imageattr.h" + +#include "tsk_ragel_state.h" +#include "tsk_debug.h" + +#include <stdlib.h> + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine tmedia_machine_imageattr; + + # Includes + include tmedia_machine_utils "./ragel/tmedia_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action is_send{ + sets = &self->send.sets[0]; + sets_count = &self->send.count; + *sets_count = 0; + } + + action is_recv{ + sets = &self->recv.sets[0]; + sets_count = &self->recv.count; + *sets_count = 0; + } + + action is_xrange{ + xyrange = (*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) ? &sets[*sets_count].xrange : tsk_null; + } + action is_yrange{ + xyrange = (*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) ? &sets[*sets_count].yrange : tsk_null; + } + action set_parsed{ + if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) (*sets_count)++; + } + action set_is_not_range{ + if(xyrange) xyrange->is_range = 0; + } + action set_is_range{ + if(xyrange) xyrange->is_range = 1; + } + action parse_xyvalue_range_start{ + if(xyrange)xyrange->range.start = atoi(tag_start); + } + action parse_xyvalue_range_step{ + if(xyrange)xyrange->range.step = atoi(tag_start); + } + action parse_xyvalue_range_end{ + if(xyrange)xyrange->range.end = atoi(tag_start); + } + action parse_xyvalue_array_value{ + if(xyrange && xyrange->array.count < TMEDIA_imageattr_ARRAY_MAX_SIZE){ + xyrange->array.values[xyrange->array.count++] = atoi(tag_start); + } + } + action set_parse_qvalue{ + if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE){ + sets[*sets_count].qvalue = atof(tag_start); + } + } + + action srange_is_array{ + if(srange) srange->is_range = 0; + } + action srange_is_not_array{ + if(srange) srange->is_range = 1; + } + action start_srange{ + srange = (*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) ? &sets[*sets_count].srange : tsk_null; + } + action parse_srange_array_value{ + if(srange && srange->array.count < TMEDIA_imageattr_ARRAY_MAX_SIZE){ + srange->array.values[srange->array.count++] = atof(tag_start); + } + } + action parse_srange_range_start{ + if(srange) srange->range.start = atof(tag_start); + } + action parse_srange_range_end{ + if(srange) srange->range.end = atof(tag_start); + } + + action parse_prange_start{ + if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) sets[*sets_count].prange.start = atof(tag_start); + } + action parse_prange_end{ + if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) sets[*sets_count].prange.end = atof(tag_start), sets[*sets_count].prange.is_present = 1; + } + + PT = DIGIT+ | "*"; + onetonine = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; + xyvalue = (onetonine DIGIT{,5}); + step = xyvalue; + xyrange = ( "[" xyvalue>tag %parse_xyvalue_range_start ":" ( step>tag %parse_xyvalue_range_step ":" )? xyvalue>tag %parse_xyvalue_range_end "]" )%set_is_range | ( "[" xyvalue>tag %parse_xyvalue_array_value ( "," xyvalue>tag %parse_xyvalue_array_value )+ "]" )%set_is_not_range | xyvalue%set_is_not_range>tag %parse_xyvalue_array_value; + spvalue = ( "0" "." onetonine DIGIT{,3} ) | ( onetonine "." DIGIT{1,4} ); + srange = (( "[" spvalue>tag %parse_srange_array_value ( "," spvalue>tag %parse_srange_array_value )+ "]" )%srange_is_array | ( "[" spvalue>tag %parse_srange_range_start "-" spvalue>tag %parse_srange_range_end "]" )%srange_is_not_array | spvalue>tag %parse_srange_array_value %srange_is_array)>start_srange; + prange = ( "[" spvalue>tag %parse_prange_start "-" spvalue>tag %parse_prange_end "]" ); + _qvalue = (( "0" "." DIGIT{1,2} ) | ( "1" "." "0"{1,2} ))>tag %set_parse_qvalue; #qvalue collision + key_value = ( "sar="i srange ) | ( "par="i prange ) | ( "q="i _qvalue ); + set = ("[" "x="i xyrange>is_xrange "," "y="i xyrange>is_yrange ( "," key_value )* "]")%set_parsed; + attr_list = ( set ( WSP+ set )* ) | "*"; + imageattr = ( WSP* ( "send"i%is_send | "recv"i%is_recv ) WSP+ attr_list ){1,2}; + + # Entry point + main:= imageattr; +}%% + +static int tmedia_imageattr_reset(tmedia_imageattr_xt* self) +{ + if(self){ + tsk_size_t i; + memset(self, 0, sizeof(*self)); + for(i = 0; i < TMEDIA_imageattr_ARRAY_MAX_SIZE; ++i){ + self->send.sets[i].qvalue = 0.5; + self->recv.sets[i].qvalue = 0.5; + } + return 0; + } + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; +} + +int tmedia_imageattr_parse(tmedia_imageattr_xt* self, const void* in_data, tsk_size_t in_size) +{ + int cs = 0; + const char *p = in_data; + const char *pe = p + in_size; + const char *eof = pe; + + const char *tag_start = tsk_null; + + tmedia_imageattr_set_xt* sets = tsk_null; + tsk_size_t* sets_count = tsk_null; + tmedia_imageattr_xyrange_xt* xyrange = tsk_null; + tmedia_imageattr_srange_xt* srange = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(tmedia_machine_imageattr_first_final); + (void)(tmedia_machine_imageattr_error); + (void)(tmedia_machine_imageattr_en_main); + %%write init; + tmedia_imageattr_reset(self); + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Parsing failed to parse image-attr=%s", (char*)in_data); + return -1; + } + + return 0; +}
\ No newline at end of file diff --git a/tinyMEDIA/ragel/tmedia_machine_utils.rl b/tinyMEDIA/ragel/tmedia_machine_utils.rl new file mode 100644 index 0000000..2dbabad --- /dev/null +++ b/tinyMEDIA/ragel/tmedia_machine_utils.rl @@ -0,0 +1,78 @@ +/* +* Copyright (C) 2010-2011 Mamadou Diop. +* +* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> +* +* 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 tmedia_machine_utils.rl + * @brief Ragel file. + * + * @author Mamadou Diop <diopmamadou(at)doubango[dot]org> + * + + */ +%%{ + + machine tmedia_machine_utils; + + OCTET = "0x"[0-9A-Fa-f]+; + CHAR = 0x01..0x7f; + VCHAR = 0x21..0x7e; + ALPHA = 0x41..0x5a | 0x61..0x7a; + DIGIT = 0x30..0x39; + CTL = 0x00..0x1f | 0x7f; + HTAB = "\t"; + LF = "\n"; + CR = "\r"; + SP = " "; + DQUOTE = "\""; + BIT = "0" | "1"; + HEXDIG = DIGIT | "A"i | "B"i | "C"i | "D"i | "E"i | "F"i; + CRLF = CR LF; + WSP = SP | HTAB; + LWSP = ( WSP | ( CRLF WSP ) )*; + LWS = ( WSP* CRLF )? WSP+; + SWS = LWS?; + EQUAL = SWS "=" SWS; + LHEX = DIGIT | 0x61..0x66; + HCOLON = ( SP | HTAB )* ":" SWS; + separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | DQUOTE | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HTAB; + STAR = SWS "*" SWS; + SLASH = SWS "/" SWS; + LPAREN = SWS "(" SWS; + RPAREN = SWS ")" SWS; + COMMA = SWS "," SWS; + SEMI = SWS ";" SWS; + COLON = SWS ":" SWS; + LAQUOT = SWS "<"; + LDQUOT = SWS DQUOTE; + RAQUOT = ">" SWS; + RDQUOT = DQUOTE SWS; + UTF8_CONT = 0x80..0xbf; + ##### FIXME: UTF8_NONASCII up to 2bytes will fail on Android + UTF8_NONASCII = ( 0x80..0xff ); + #UTF8_NONASCII = ( 0xc0..0xdf UTF8_CONT ) | ( 0xe0..0xef UTF8_CONT{2} ) | ( 0xf0..0xf7 UTF8_CONT{3} ) | ( 0xf8..0xfb UTF8_CONT{4} ) | ( 0xfc..0xfd UTF8_CONT{5} ); ctext = 0x21..0x27 | 0x2a..0x5b | 0x5d..0x7e | UTF8_NONASCII | LWS; + qvalue = ( "0" ( "." DIGIT{,3} )? ) | ( "1" ( "." "0"{,3} )? ); + alphanum = ALPHA | DIGIT; + token = ( alphanum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" )+; + ietf_token = token; + x_token = "x-"i token; + iana_token = token; + token_nodot = ( alphanum | "-" | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" )+; + word = ( alphanum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" | "(" | ")" | "<" | ">" | ":" | "\\" | DQUOTE | "/" | "[" | "]" | "?" | "{" | "}" )+; +}%% |