Sebastián Pastor / EtheriosCloudConnector
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rci_binary_input.h Source File

rci_binary_input.h

00001 /*
00002  * Copyright (c) 2013 Digi International Inc.,
00003  * All rights not expressly granted are reserved.
00004  *
00005  * This Source Code Form is subject to the terms of the Mozilla Public
00006  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
00007  * You can obtain one at http://mozilla.org/MPL/2.0/.
00008  *
00009  * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
00010  * =======================================================================
00011  */
00012 
00013 
00014 #if defined RCI_PARSER_USES_ERROR_DESCRIPTIONS
00015 static char const rci_set_empty_group_hint[] = "Empty group";
00016 static char const rci_set_empty_element_hint[] = "empty element";
00017 static char const rci_error_descriptor_mismatch_hint[] = "Mismatch configurations";
00018 static char const rci_error_content_size_hint[] = "Maximum content size exceeded";
00019 #else
00020 #define rci_set_empty_group_hint            RCI_NO_HINT
00021 #define rci_set_empty_element_hint          RCI_NO_HINT
00022 #define rci_error_descriptor_mismatch_hint  RCI_NO_HINT
00023 #define rci_error_content_size_hint         RCI_NO_HINT
00024 #endif
00025 
00026 static connector_bool_t destination_in_storage(rci_t const * const rci)
00027 {
00028     uint8_t const * const storage_begin = rci->input.storage;
00029     uint8_t const * const storage_end = storage_begin + sizeof rci->input.storage;
00030 
00031     return ptr_in_range(rci->input.destination, storage_begin, storage_end);
00032 }
00033 
00034 static size_t get_bytes_to_follow(uint8_t opcode)
00035 {
00036     size_t bytes_to_read = 0;
00037 
00038     if (opcode & BINARY_RCI_SIZE_ALTERNATE_FLAG)
00039     {
00040         rci_size_modifier_t size_mask = BINARY_RCI_SIZE_MODIFIER(opcode);
00041         switch (size_mask)
00042         {
00043         case binary_rci_one_follow_byte:
00044             bytes_to_read = 1;
00045             break;
00046         case binary_rci_multi_follow_byte:
00047             switch (BINARY_RCI_MULTI_FOLLOW_BYTES(opcode))
00048             {
00049                 case binary_rci_two_follow_byte:
00050                     bytes_to_read = 2;
00051                     break;
00052                 case binary_rci_four_follow_byte:
00053                     bytes_to_read = 4;
00054                     break;
00055                 case binary_rci_eight_follow_byte:
00056                     bytes_to_read = 8;
00057                     break;
00058             }
00059             break;
00060         case binary_rci_special_value:
00061             bytes_to_read = 0;
00062             break;
00063         default:
00064             ASSERT(connector_false);
00065         }
00066     }
00067     return bytes_to_read;
00068 }
00069 
00070 static void reset_input_content(rci_t * const rci)
00071 {
00072     rci->shared.content.data = rci->input.destination;
00073     rci->shared.content.length = 0;
00074 }
00075 
00076 #define BINARY_RCI_ONE_BYTE_LIMIT_MASK  UINT32_C(0x7F)
00077 #define BINARY_RCI_HI_BYTE_MASK         UINT32_C(0x1F)
00078 
00079 static size_t get_modifier_ber(rci_t * const rci, uint32_t * const value)
00080 {
00081 
00082     uint8_t * const rci_ber = rci->shared.content.data;
00083     uint8_t const modifier_ber = message_load_u8(rci_ber, value);
00084 
00085     size_t bytes_read = ++rci->shared.content.length;
00086 
00087     {
00088         /* we have modifier BEF */
00089         size_t const bytes_to_follow = get_bytes_to_follow(modifier_ber) +1;
00090 
00091         bytes_read = rci->shared.content.length;
00092 
00093         if (bytes_read < bytes_to_follow)
00094         {
00095             bytes_read = 0;
00096             goto done;
00097         }
00098 
00099         switch (bytes_to_follow)
00100         {
00101             case record_bytes(rci_ber):
00102                *value =  (modifier_ber & BINARY_RCI_SIZE_ALTERNATE_FLAG) ? modifier_ber : (modifier_ber & BINARY_RCI_ONE_BYTE_LIMIT_MASK);
00103                 break;
00104             case record_bytes(rci_ber_u8):
00105             {
00106                 uint8_t * const rci_ber_u8 = rci_ber;
00107                 /* mask of the 1st byte for data value */
00108                 *value = (modifier_ber & BINARY_RCI_HI_BYTE_MASK) << 8;
00109                 *value |= message_load_u8(rci_ber_u8, value);
00110                 break;
00111             }
00112             case record_bytes(rci_ber_u16):
00113             {
00114                 uint8_t * const rci_ber_u16 = rci_ber;
00115                 *value = message_load_be16(rci_ber_u16, value);
00116                 break;
00117             }
00118             case record_bytes(rci_ber_u32):
00119             {
00120                 uint8_t * const rci_ber_u32 = rci_ber;
00121                 *value = message_load_be32(rci_ber_u32, value);
00122                 break;
00123             }
00124             default:
00125                 ASSERT(bytes_to_follow == 1);
00126                 /* NONUM or TRM value */
00127                 *value = modifier_ber;
00128                 break;
00129         }
00130         bytes_read = bytes_to_follow;
00131     }
00132 
00133 done:
00134     return bytes_read;
00135 }
00136 
00137 static connector_bool_t get_uint32(rci_t * const rci, uint32_t * const value)
00138 {
00139 
00140     size_t const bytes = get_modifier_ber(rci, value);
00141 
00142     if (bytes > 0)
00143         reset_input_content(rci);
00144 
00145     return connector_bool(bytes > 0);
00146 }
00147 
00148 #if defined RCI_PARSER_USES_FLOAT
00149 static connector_bool_t get_float(rci_t * const rci, float * const value)
00150 {
00151 
00152     connector_bool_t value_decoded = connector_false;
00153     uint8_t * rci_ber_u32 = rci->shared.content.data;
00154     uint8_t const opcode = message_load_u8(rci_ber_u32, opcode);
00155 
00156     rci->shared.content.length++;
00157     ASSERT(sizeof(uint32_t) == sizeof(float));
00158 
00159     {
00160         /* we have modifier BEF */
00161         size_t const bytes_to_follow = get_bytes_to_follow(opcode);
00162         size_t bytes_read = rci->shared.content.length;
00163 
00164         if (bytes_read < (bytes_to_follow + 1))
00165         {
00166             goto error;
00167         }
00168 
00169         /* Current, we only support single precision float. */
00170         ASSERT(bytes_read == record_bytes(rci_ber_u32));
00171 
00172         {
00173             uint32_t float_value = message_load_be32(rci_ber_u32, value);
00174             memcpy(value, &float_value, sizeof *value);
00175         }
00176     }
00177 
00178     value_decoded = connector_true;
00179     reset_input_content(rci);
00180 
00181 error:
00182     return value_decoded;
00183 }
00184 #endif
00185 
00186 static connector_bool_t get_string(rci_t * const rci, char const * * string, size_t * const length)
00187 {
00188     connector_bool_t got_string = connector_false;
00189     uint32_t value;
00190     size_t const ber_bytes = get_modifier_ber(rci, &value);
00191 
00192     if (ber_bytes > 0)
00193     {
00194         size_t const bytes = rci->shared.content.length;
00195 #if defined CONNECTOR_DEBUG
00196         size_t const size_max = SIZE_MAX;
00197 
00198         (void)size_max;
00199         ASSERT(value <= size_max);
00200 #endif
00201         *length = value;
00202         if (*length > CONNECTOR_RCI_MAXIMUM_CONTENT_LENGTH)
00203         {
00204             connector_debug_printf("Maximum content size exceeded while getting  a string - wanted %u, had %u\n", *length, CONNECTOR_RCI_MAXIMUM_CONTENT_LENGTH);
00205             rci_set_output_error(rci, connector_rci_error_bad_descriptor, rci_error_content_size_hint, rci_output_state_field_id);
00206             goto done;
00207         }
00208 
00209         if (bytes == (ber_bytes + *length))
00210         {
00211             char * data = (char *)(rci->shared.content.data + ber_bytes);
00212 
00213             if (!destination_in_storage(rci))
00214             {
00215                 memcpy(rci->input.storage, data, *length);
00216                 data = (char *)rci->input.storage;
00217             }
00218 
00219             data[*length] = nul;
00220             *string =  data;
00221 
00222             reset_input_content(rci);
00223             got_string = connector_true;
00224         }
00225     }
00226 done:
00227     return got_string;
00228 }
00229 
00230 #if defined RCI_PARSER_USES_IPV4
00231 static connector_bool_t get_ip_address(rci_t * const rci, uint32_t * const ip_addr, size_t const length)
00232 {
00233     connector_bool_t got_ip = connector_false;
00234 
00235     uint8_t * rci_ber_u32 = rci->shared.content.data;
00236     uint8_t const bytes_read = message_load_u8(rci_ber_u32, opcode);
00237 
00238     UNUSED_PARAMETER(length);
00239 
00240     rci->shared.content.length++;
00241 
00242     if (rci->shared.content.length == (size_t)(bytes_read + 1))
00243     {
00244         /* Current, we only support ipv4. */
00245         ASSERT(bytes_read == sizeof *ip_addr);
00246         ASSERT(length == bytes_read);
00247 
00248         *ip_addr = message_load_be32(rci_ber_u32, value);
00249 
00250         got_ip = connector_true;
00251         reset_input_content(rci);
00252     }
00253 
00254     return got_ip;
00255 }
00256 #endif
00257 
00258 static connector_bool_t decode_attribute(rci_t * const rci, unsigned int * index)
00259 {
00260 #define BINARY_RCI_ATTRIBUTE_TYPE_MASK  0x60  /* attr type: [bit 6 and 5] */
00261 
00262 #define BINARY_RCI_ATTRIBUTE_TYPE_NORMAL 0x00
00263 #define BINARY_RCI_ATTRIBUTE_TYPE_INDEX  0x20
00264 #define BINARY_RCI_ATTRIBUTE_TYPE_NAME   0x40
00265 
00266 #define BINARY_RCI_ATTRIBUTE_INDEX_MASK 0x1F
00267 
00268     connector_bool_t got_attribute = connector_false;
00269     uint32_t attribute_value;
00270 
00271     if (get_uint32(rci, &attribute_value))
00272     {
00273         unsigned int type = attribute_value & BINARY_RCI_ATTRIBUTE_TYPE_MASK;
00274         switch (type)
00275         {
00276             case BINARY_RCI_ATTRIBUTE_TYPE_INDEX:
00277                 *index =  attribute_value & BINARY_RCI_ATTRIBUTE_INDEX_MASK;
00278                 rci_debug_printf("decode_attribute: index = %d\n", *index);
00279                 got_attribute = connector_true;
00280                 break;
00281             case BINARY_RCI_ATTRIBUTE_TYPE_NAME:
00282             case BINARY_RCI_ATTRIBUTE_TYPE_NORMAL:
00283                 /* Tool doesn't support name and enum attribute */
00284                 connector_debug_printf("decode_attribute: unsupported attribute type\n");
00285                 rci->status = rci_status_internal_error;
00286                 ASSERT(connector_false);
00287                 break;
00288         }
00289     }
00290 
00291     return got_attribute;
00292 }
00293 
00294 static connector_bool_t has_rci_atribute(unsigned int data)
00295 {
00296     return connector_bool((data & BINARY_RCI_ATTRIBUTE_BIT) == BINARY_RCI_ATTRIBUTE_BIT);
00297 }
00298 
00299 static connector_bool_t has_rci_error(rci_t * const rci, unsigned int data)
00300 {
00301 
00302     connector_bool_t const hasError = connector_bool((data & BINARY_RCI_ERROR_INDICATOR_BIT) == BINARY_RCI_ERROR_INDICATOR_BIT);
00303 
00304     UNUSED_PARAMETER(rci);
00305 
00306     if (hasError)
00307     {
00308         connector_debug_printf("has_rci_error: unexpected error set.\n");
00309     }
00310     return hasError;
00311 }
00312 
00313 static connector_bool_t has_rci_terminated(unsigned int data)
00314 {
00315     return connector_bool(data == BINARY_RCI_TERMINATOR);
00316 }
00317 
00318 static connector_bool_t has_rci_no_value(unsigned int data)
00319 {
00320     return connector_bool(data == BINARY_RCI_NO_VALUE);
00321 }
00322 
00323 static void process_rci_command(rci_t * const rci)
00324 {
00325 #define BINARY_RCI_COMMAND_MASK   0x3F
00326 
00327     uint32_t command;
00328 
00329     {
00330         connector_remote_config_t const * const remote_config = &rci->shared.callback_data;
00331 
00332         if (remote_config->error_id != connector_success)
00333         {
00334             set_rci_output_state(rci, rci_output_state_field_id);
00335             state_call(rci, rci_parser_state_output);
00336             goto done;
00337         }
00338     }
00339 
00340     if (get_uint32(rci, &command))
00341     {
00342 
00343         connector_bool_t const has_attribute = has_rci_atribute(command);
00344 
00345         ASSERT_GOTO(!has_rci_error(rci, command), done);
00346 
00347         command &= BINARY_RCI_COMMAND_MASK;
00348 
00349         switch (command)
00350         {
00351             case rci_command_set_setting:
00352             case rci_command_query_setting:
00353                 rci->shared.callback_data.group.type = connector_remote_group_setting;
00354                 break;
00355             case rci_command_set_state:
00356             case rci_command_query_state:
00357                 rci->shared.callback_data.group.type = connector_remote_group_state;
00358                 break;
00359         }
00360 
00361         switch (command)
00362         {
00363             case rci_command_set_setting:
00364             case rci_command_set_state:
00365                 rci->shared.callback_data.action = connector_remote_action_set;
00366                 break;
00367             case rci_command_query_setting:
00368             case rci_command_query_state:
00369                 rci->shared.callback_data.action = connector_remote_action_query;
00370                 break;
00371             default:
00372                 /* unsupported command.
00373                  * Just go to error state for returning error message.
00374                  */
00375                 rci_global_error(rci, connector_rci_error_bad_command, RCI_NO_HINT);
00376                 set_rci_command_error(rci);
00377                 state_call(rci, rci_parser_state_error);
00378                 goto done;
00379         }
00380 
00381         if (has_attribute)
00382         {
00383             set_rci_input_state(rci, rci_input_state_command_attribute);
00384         }
00385         else
00386         {
00387             set_rci_input_state(rci, rci_input_state_group_id);
00388 
00389             set_rci_traverse_state(rci, rci_traverse_state_command_id);
00390             state_call(rci, rci_parser_state_traverse);
00391         }
00392 
00393     }
00394 done:
00395     return;
00396 }
00397 
00398 static void process_command_attribute(rci_t * const rci)
00399 {
00400     unsigned int index;
00401 
00402     if (decode_attribute(rci, &index))
00403     {
00404         /* We don't support command attribute; so just ignore it. */
00405         set_rci_input_state(rci, rci_input_state_group_id);
00406 
00407         set_rci_traverse_state(rci, rci_traverse_state_command_id);
00408         state_call(rci, rci_parser_state_traverse);
00409     }
00410 
00411     return;
00412 }
00413 
00414 
00415 static void process_group_id(rci_t * const rci)
00416 {
00417     uint32_t group_id;
00418 
00419     if (!get_uint32(rci, &group_id))
00420     {
00421         goto done;
00422     }
00423 
00424     ASSERT_GOTO(!has_rci_error(rci, group_id), done);
00425 
00426     if (has_rci_terminated(group_id))
00427     {
00428         if (have_group_id(rci))
00429         {
00430             /* not 1st group */
00431             set_rci_input_state(rci, rci_input_state_command_id);
00432 
00433             set_rci_traverse_state(rci, rci_traverse_state_group_end);
00434             state_call(rci, rci_parser_state_traverse);
00435             goto done;
00436         }
00437         else
00438         {
00439             /* Get all groups if no group has been requested before */
00440             switch (rci->shared.callback_data.action)
00441             {
00442                 case connector_remote_action_query:
00443                     set_rci_traverse_state(rci, rci_traverse_state_all_groups);
00444                     state_call(rci, rci_parser_state_traverse);
00445                     break;
00446                 case connector_remote_action_set:
00447                     connector_debug_printf("process_group_id: got set command with no group id specified\n");
00448                     rci_set_output_error(rci, connector_rci_error_bad_command, rci_set_empty_group_hint, rci_output_state_group_id);
00449                     break;
00450             }
00451             goto done;
00452         }
00453     }
00454     else
00455     {
00456         set_group_id(rci, decode_group_id(group_id));
00457 
00458         if (!have_group_id(rci))
00459         {
00460             connector_debug_printf("process_group_id: unrecognized group (mismatch of descriptors) group id = %d.\n", decode_group_id(group_id));
00461             rci_set_output_error(rci, connector_rci_error_bad_descriptor, rci_error_descriptor_mismatch_hint, rci_output_state_group_id);
00462             ASSERT(connector_false);
00463             goto done;
00464         }
00465 
00466         if (has_rci_atribute(group_id))
00467         {
00468             invalidate_group_index(rci);
00469             set_rci_input_state(rci, rci_input_state_group_attribute);
00470             goto done;
00471         }
00472 
00473         {
00474             connector_group_t const * const group =  get_current_group(rci);
00475             if (group->instances > 1)
00476             {
00477                 set_rci_input_flag(rci, RCI_FLAG_GET_ALL_INSTANCES);
00478             }
00479         }
00480 
00481         set_rci_input_state(rci, rci_input_state_field_id);
00482     }
00483 
00484     set_group_index(rci, 1);
00485     set_rci_traverse_state(rci, rci_traverse_state_group_id);
00486     state_call(rci, rci_parser_state_traverse);
00487     rci_debug_printf("process_group_id: group id = %d\n", get_group_id(rci));
00488 
00489 done:
00490     return;
00491 }
00492 
00493 static void process_group_attribute(rci_t * const rci)
00494 {
00495     if (decode_attribute(rci, &rci->shared.group.index))
00496     {
00497         set_rci_input_state(rci, rci_input_state_field_id);
00498         set_rci_traverse_state(rci, rci_traverse_state_group_id);
00499         state_call(rci, rci_parser_state_traverse);
00500     }
00501 
00502     return;
00503 }
00504 
00505 static void process_field_id(rci_t * const rci)
00506 {
00507     unsigned int id = INVALID_ID;
00508     {
00509         uint32_t value;
00510 
00511         if (!get_uint32(rci, &value))
00512         {
00513             goto done;
00514         }
00515 
00516         /* Bit 6  - is Field type present indicator
00517          * Bit 10 - is attributes present indicator
00518          * Bit 12 - is Error indicator (Should not be set)
00519          */
00520         ASSERT_GOTO(!has_rci_error(rci, value), done);
00521 
00522         if (has_rci_terminated(value))
00523         {
00524             if (!have_element_id(rci))
00525             {
00526                 switch (rci->shared.callback_data.action)
00527                 {
00528                     case connector_remote_action_query:
00529                         /* all fields */
00530                         if (is_rci_input_flag(rci,RCI_FLAG_GET_ALL_INSTANCES))
00531                             set_rci_traverse_state(rci, rci_traverse_state_all_group_instances);
00532                         else
00533                             set_rci_traverse_state(rci, rci_traverse_state_all_elements);
00534 
00535                         set_rci_input_state(rci, rci_input_state_group_id);
00536 
00537                         state_call(rci, rci_parser_state_traverse);
00538                         break;
00539                     case connector_remote_action_set:
00540                         connector_debug_printf("process_field_id: got set command with no field id specified\n");
00541                         rci_set_output_error(rci, connector_rci_error_bad_command, rci_set_empty_element_hint, rci_output_state_field_id);
00542                         break;
00543                 }
00544             }
00545             else
00546             {
00547                 /* done with all fields */
00548                 invalidate_element_id(rci);
00549                 set_rci_input_state(rci, rci_input_state_group_id);
00550 
00551                 set_rci_traverse_state(rci, rci_traverse_state_element_end);
00552                 state_call(rci, rci_parser_state_traverse);
00553             }
00554             goto done;
00555         }
00556 
00557         if ((value & BINARY_RCI_FIELD_TYPE_INDICATOR_BIT) == BINARY_RCI_FIELD_TYPE_INDICATOR_BIT)
00558         {
00559             set_rci_input_state(rci, rci_input_state_field_type);
00560         }
00561         else
00562         {
00563             set_rci_input_state(rci, rci_input_state_field_no_value);
00564         }
00565 
00566 
00567         if ((value & BINARY_RCI_FIELD_ATTRIBUTE_BIT) == BINARY_RCI_FIELD_ATTRIBUTE_BIT)
00568         {
00569             connector_debug_printf("process_field_id: field attribute is not supported\n");
00570             rci_set_output_error(rci, connector_rci_error_bad_descriptor, RCI_NO_HINT, rci_output_state_field_id);
00571             goto done;
00572         }
00573 
00574         id = decode_element_id(value);
00575 
00576     }
00577 
00578 
00579     set_element_id(rci, id);
00580 
00581     if (!have_element_id(rci))
00582     {
00583         connector_debug_printf("process_field_id: unrecognized field id (mismatch of descriptors). element id = %d\n", id);
00584         rci_set_output_error(rci, connector_rci_error_bad_descriptor, rci_error_descriptor_mismatch_hint, rci_output_state_field_id);
00585     }
00586 
00587 done:
00588     return;
00589 }
00590 
00591 static void process_field_type(rci_t * const rci)
00592 {
00593     connector_group_element_t const * const element = get_current_element(rci);
00594     connector_bool_t error = connector_false;
00595     uint32_t type;
00596 
00597     if (get_uint32(rci, &type))
00598     {
00599         ASSERT_GOTO(!has_rci_error(rci, type), done);
00600 
00601         switch (type)
00602         {
00603             case rci_field_type_none:
00604                 break;
00605 
00606             default:
00607                 if (element->type != type)
00608                 {
00609                     connector_debug_printf("process_field_type: mismatch field type (type %d) != (actual %d)\n", type, element->type);
00610                     rci_set_output_error(rci, connector_rci_error_bad_descriptor, rci_error_descriptor_mismatch_hint, rci_output_state_field_id);
00611                     error = connector_true;
00612                 }
00613                 break;
00614         }
00615     }
00616 
00617     if (!error)
00618     {
00619         set_rci_input_state(rci, rci_input_state_field_no_value);
00620     }
00621 
00622 done:
00623     return;
00624 }
00625 
00626 static void process_field_value(rci_t * const rci)
00627 {
00628     connector_group_element_t const * const element = get_current_element(rci);
00629     connector_element_value_type_t const type = element->type;
00630 
00631 #if (defined RCI_PARSER_USES_ON_OFF) || (defined RCI_PARSER_USES_BOOLEAN)
00632     connector_bool_t error = connector_false;
00633 #endif
00634 
00635     switch (type)
00636     {
00637 #if defined RCI_PARSER_USES_STRINGS
00638 
00639 #if defined RCI_PARSER_USES_STRING
00640     case connector_element_type_string:
00641 #endif
00642 
00643 #if defined RCI_PARSER_USES_MULTILINE_STRING
00644     case connector_element_type_multiline_string:
00645 #endif
00646 
00647 #if defined RCI_PARSER_USES_PASSWORD
00648     case connector_element_type_password:
00649 #endif
00650 
00651 
00652 #if defined RCI_PARSER_USES_FQDNV4
00653     case connector_element_type_fqdnv4:
00654 #endif
00655 
00656 #if defined RCI_PARSER_USES_FQDNV6
00657     case connector_element_type_fqdnv6:
00658 #endif
00659 
00660 #if defined RCI_PARSER_USES_DATETIME
00661     case connector_element_type_datetime:
00662 #endif
00663         if (!get_string(rci, &rci->shared.value.string_value, &rci->shared.string_value_length))
00664         {
00665             goto done;
00666         }
00667         break;
00668 #endif
00669 
00670 
00671 #if defined RCI_PARSER_USES_INT32
00672     case connector_element_type_int32:
00673     {
00674         int32_t value;
00675 
00676         if (!get_uint32(rci, (uint32_t *)&value))
00677         {
00678             goto done;
00679         }
00680         rci->shared.value.signed_integer_value = value;
00681         break;
00682     }
00683 #endif
00684 
00685 #if defined RCI_PARSER_USES_IPV4
00686     case connector_element_type_ipv4:
00687     {
00688         uint32_t ip_addr;
00689 
00690         if (!get_ip_address(rci, &ip_addr, sizeof ip_addr))
00691         {
00692             goto done;
00693         }
00694 
00695         {
00696             #define MAX_IPV4_VALUE "255.255.255.255"
00697 
00698             char * const data = (char *)rci->input.storage;
00699             size_t const size_avail = sizeof MAX_IPV4_VALUE;
00700             int size_written;
00701 
00702             uint8_t ip1 = BYTE32_3(ip_addr);
00703             uint8_t ip2 = BYTE32_2(ip_addr);
00704             uint8_t ip3 = BYTE32_1(ip_addr);
00705             uint8_t ip4 = BYTE32_0(ip_addr);
00706 
00707             ASSERT(size_avail <= sizeof rci->input.storage);
00708 
00709             size_written = connector_snprintf(data, size_avail, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
00710 
00711             ASSERT(size_written < (int)size_avail);
00712             ASSERT_GOTO(size_written > 0, done);
00713 
00714             rci->shared.value.string_value = data;
00715 
00716             #undef MAX_IPV4_VALUE
00717         }
00718         break;
00719     }
00720 #endif
00721 
00722 #if (defined RCI_PARSER_USES_UNSIGNED_INTEGER)
00723 
00724 
00725 #if defined RCI_PARSER_USES_UINT32
00726     case connector_element_type_uint32:
00727 #endif
00728 
00729 #if defined RCI_PARSER_USES_HEX32
00730     case connector_element_type_hex32:
00731 #endif
00732 
00733 #if defined RCI_PARSER_USES_0X_HEX32
00734     case connector_element_type_0x_hex32:
00735 #endif
00736     {
00737         uint32_t value;
00738 
00739         if (!get_uint32(rci, &value))
00740         {
00741             goto done;
00742         }
00743         rci->shared.value.unsigned_integer_value = value;
00744         break;
00745     }
00746 #endif
00747 
00748 #if defined RCI_PARSER_USES_FLOAT
00749     case connector_element_type_float:
00750     {
00751         if (!get_float(rci, &rci->shared.value.float_value))
00752         {
00753             goto done;
00754         }
00755         break;
00756     }
00757 #endif
00758 
00759 #if defined RCI_PARSER_USES_ENUM
00760     case connector_element_type_enum:
00761     {
00762         uint32_t value;
00763         if (!get_uint32(rci, &value))
00764         {
00765             goto done;
00766         }
00767         rci->shared.value.enum_value = value;
00768         break;
00769     }
00770 #endif
00771 
00772 #if defined RCI_PARSER_USES_ON_OFF
00773     case connector_element_type_on_off:
00774     {
00775         uint32_t value;
00776 
00777         if (!get_uint32(rci, &value))
00778         {
00779             goto done;
00780         }
00781         rci->shared.value.on_off_value = (value == 0)? connector_off : connector_on;
00782         error = connector_bool((value != 0) && (value != 1));
00783         break;
00784     }
00785 #endif
00786 
00787 #if defined RCI_PARSER_USES_BOOLEAN
00788     case connector_element_type_boolean:
00789     {
00790         uint32_t value;
00791         if (!get_uint32(rci, &value))
00792         {
00793             goto done;
00794         }
00795         rci->shared.value.boolean_value = (value == 0)? connector_false : connector_true;
00796         error = connector_bool((value != 0) && (value != 1));
00797         break;
00798     }
00799 #endif
00800     }
00801 
00802 #if (defined RCI_PARSER_USES_ON_OFF) || (defined RCI_PARSER_USES_BOOLEAN)
00803     if (error)
00804     {
00805         connector_debug_printf("process_field_value: range check error! Descriptor problem!");
00806         rci_set_output_error(rci, connector_rci_error_bad_descriptor, rci_error_descriptor_mismatch_hint, rci_output_state_field_id);
00807     }
00808     else
00809 #endif
00810     {
00811         set_rci_traverse_state(rci, rci_traverse_state_element_id);
00812         state_call(rci, rci_parser_state_traverse);
00813     }
00814     set_rci_input_state(rci, rci_input_state_field_id);
00815 
00816 done:
00817     return;
00818 }
00819 
00820 static void process_field_no_value(rci_t * const rci)
00821 {
00822     uint8_t * const rci_ber = rci->shared.content.data;
00823     uint8_t const modifier_ber = message_load_u8(rci_ber, value);
00824 
00825     if (has_rci_no_value(modifier_ber))
00826     {
00827         /* this initializes element.value in case for set setting */
00828         connector_group_element_t const * const element = get_current_element(rci);
00829         connector_element_value_type_t const type = element->type;
00830 
00831         switch (type)
00832         {
00833 #if defined RCI_PARSER_USES_STRINGS
00834 
00835     #if defined RCI_PARSER_USES_STRING
00836         case connector_element_type_string:
00837     #endif
00838 
00839     #if defined RCI_PARSER_USES_MULTILINE_STRING
00840         case connector_element_type_multiline_string:
00841     #endif
00842 
00843     #if defined RCI_PARSER_USES_PASSWORD
00844         case connector_element_type_password:
00845     #endif
00846 
00847 
00848     #if defined RCI_PARSER_USES_FQDNV4
00849         case connector_element_type_fqdnv4:
00850     #endif
00851 
00852     #if defined RCI_PARSER_USES_FQDNV6
00853         case connector_element_type_fqdnv6:
00854     #endif
00855 
00856     #if defined RCI_PARSER_USES_DATETIME
00857         case connector_element_type_datetime:
00858     #endif
00859 
00860     #if defined RCI_PARSER_USES_IPV4
00861         case connector_element_type_ipv4:
00862     #endif
00863             rci->shared.value.string_value = (char *)rci->input.storage;
00864             rci->input.storage[0] = (uint8_t)nul;
00865             break;
00866 #endif
00867 
00868 #if defined RCI_PARSER_USES_INT32
00869         case connector_element_type_int32:
00870             rci->shared.value.signed_integer_value = 0;
00871             break;
00872 #endif
00873 
00874 #if (defined RCI_PARSER_USES_UNSIGNED_INTEGER)
00875 
00876 
00877 #if defined RCI_PARSER_USES_UINT32
00878         case connector_element_type_uint32:
00879 #endif
00880 
00881 #if defined RCI_PARSER_USES_HEX32
00882         case connector_element_type_hex32:
00883 #endif
00884 
00885 #if defined RCI_PARSER_USES_0X_HEX32
00886         case connector_element_type_0x_hex32:
00887 #endif
00888             rci->shared.value.unsigned_integer_value = 0;
00889             break;
00890 #endif
00891 
00892 #if defined RCI_PARSER_USES_FLOAT
00893         case connector_element_type_float:
00894             rci->shared.value.float_value = 0;
00895             break;
00896 #endif
00897 
00898 #if defined RCI_PARSER_USES_ENUM
00899         case connector_element_type_enum:
00900             rci->shared.value.enum_value = 0;
00901             break;
00902 #endif
00903 
00904 #if defined RCI_PARSER_USES_ON_OFF
00905         case connector_element_type_on_off:
00906             rci->shared.value.on_off_value = connector_off;
00907             break;
00908 #endif
00909 
00910 #if defined RCI_PARSER_USES_BOOLEAN
00911         case connector_element_type_boolean:
00912             rci->shared.value.boolean_value = connector_false;
00913             break;
00914 #endif
00915         }
00916 
00917         reset_input_content(rci);
00918         set_rci_traverse_state(rci, rci_traverse_state_element_id);
00919         state_call(rci, rci_parser_state_traverse);
00920         set_rci_input_state(rci, rci_input_state_field_id);
00921     }
00922     else
00923     {
00924         set_rci_input_state(rci, rci_input_state_field_value);
00925         process_field_value(rci);
00926     }
00927 
00928 }
00929 
00930 static void rci_parse_input(rci_t * const rci)
00931 {
00932     rci_buffer_t * const input = &rci->buffer.input;
00933 
00934     while ((rci->parser.state == rci_parser_state_input) && (rci_buffer_remaining(input) != 0))
00935     {
00936 
00937         if (rci->input.destination != rci_buffer_position(&rci->buffer.input))
00938         {
00939             *(rci->input.destination) = rci_buffer_read(input);
00940         }
00941         rci->input.destination++;
00942 
00943         rci_debug_printf("input: %s\n", rci_input_state_t_as_string(rci->input.state));
00944 
00945         switch (rci->input.state)
00946         {
00947             case rci_input_state_command_id:
00948                 process_rci_command(rci);
00949                 break;
00950             case rci_input_state_command_attribute:
00951                 process_command_attribute(rci);
00952                 break;
00953             case rci_input_state_group_id:
00954                 process_group_id(rci);
00955                 break;
00956             case rci_input_state_group_attribute:
00957                 process_group_attribute(rci);
00958                 break;
00959             case rci_input_state_field_id:
00960                 process_field_id(rci);
00961                 break;
00962             case rci_input_state_field_type:
00963                 process_field_type(rci);
00964                 break;
00965             case rci_input_state_field_no_value:
00966                 process_field_no_value(rci);
00967                 break;
00968             case rci_input_state_field_value:
00969                 process_field_value(rci);
00970                 break;
00971             case rci_input_state_done:
00972                 break;
00973         }
00974 
00975         {
00976             size_t const storage_bytes = sizeof rci->input.storage;
00977             uint8_t const * const storage_end = rci->input.storage + storage_bytes;
00978 
00979             if (rci->input.destination == storage_end)
00980             {
00981                 connector_debug_printf("Maximum content size exceeded while parsing - wanted %u, had %u\n", storage_bytes + 1, storage_bytes);
00982                 rci_set_output_error(rci, connector_rci_error_bad_descriptor, rci_error_content_size_hint, rci_output_state_field_id);
00983                 goto done;
00984             }
00985         }
00986 
00987         rci_buffer_advance(input, 1);
00988     }
00989 
00990     if (rci_buffer_remaining(input) == 0)
00991     {
00992         if (MsgIsLastData(rci->service_data->input.flags))
00993         {
00994             set_rci_input_state(rci, rci_input_state_done);
00995             state_call(rci, rci_parser_state_traverse);
00996         }
00997         else
00998         {
00999             uint8_t const * const old_base = rcistr_data(&rci->shared.content);
01000             uint8_t * const new_base = destination_in_storage(rci) ? rci->input.destination : rci->input.storage;
01001 
01002             if (ptr_in_buffer(old_base, &rci->buffer.input))
01003             {
01004                 size_t const storage_bytes = sizeof rci->input.storage;
01005                 uint8_t const * const storage_end = rci->input.storage + storage_bytes;
01006                 size_t const bytes_wanted = (size_t)(rci->buffer.input.end - old_base);
01007                 size_t const bytes_have = (size_t)(storage_end - new_base);
01008 
01009                 if (bytes_wanted >= bytes_have)
01010                 {
01011                     connector_debug_printf("Maximum content size exceeded while storing - wanted %u, had %u\n", bytes_wanted, bytes_have);
01012                     rci_set_output_error(rci, connector_rci_error_bad_descriptor, rci_error_content_size_hint, rci_output_state_field_id);
01013                     goto done;
01014                 }
01015 
01016                 memcpy(new_base, old_base, bytes_wanted);
01017 
01018                 adjust_rcistr(new_base, old_base, &rci->shared.content);
01019                 rci->input.destination = new_base + bytes_wanted;
01020             }
01021 
01022             rci->status = rci_status_more_input;
01023         }
01024     }
01025 
01026 done:
01027     return;
01028 }
01029 
01030