Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
connector_sm_recv.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 #if (defined CONNECTOR_TRANSPORT_SMS) 00013 static connector_status_t sm_decode_segment(connector_data_t * const connector_ptr, connector_sm_packet_t * const recv_ptr) 00014 { 00015 size_t const data_size = 1 + ((recv_ptr->total_bytes - recv_ptr->processed_bytes) * 4)/5; 00016 void * data_ptr = NULL; 00017 connector_status_t result = malloc_data_buffer(connector_ptr, data_size, named_buffer_id(sm_data_block), &data_ptr); 00018 00019 if (result == connector_working) 00020 { 00021 recv_ptr->total_bytes = sm_decode85(data_ptr, data_size, recv_ptr->data + recv_ptr->processed_bytes, recv_ptr->total_bytes - recv_ptr->processed_bytes); 00022 memcpy(recv_ptr->data, data_ptr, recv_ptr->total_bytes); 00023 result = free_data_buffer(connector_ptr, named_buffer_id(sm_data_block), data_ptr); 00024 } 00025 00026 return result; 00027 } 00028 00029 static connector_status_t sm_verify_sms_preamble(connector_sm_data_t * const sm_ptr) 00030 { 00031 connector_status_t result = connector_working; 00032 00033 if (sm_ptr->transport.id_length > 0) 00034 { 00035 uint8_t * const data_ptr = sm_ptr->network.recv_packet.data; 00036 char const prefix = '('; 00037 char const suffix[] = "):"; 00038 size_t const suffix_bytes = sizeof suffix - 1; 00039 size_t const prefix_bytes = sizeof prefix; 00040 size_t const suffix_position = prefix_bytes + sm_ptr->transport.id_length; 00041 connector_bool_t const valid_prefix = connector_bool(*data_ptr == prefix); 00042 connector_bool_t const valid_shared_key = connector_bool(memcmp(data_ptr + prefix_bytes, sm_ptr->transport.id, sm_ptr->transport.id_length) == 0); 00043 connector_bool_t const valid_suffix = connector_bool(memcmp(data_ptr + suffix_position, suffix, suffix_bytes) == 0); 00044 00045 if (valid_prefix && valid_shared_key && valid_suffix) 00046 sm_ptr->network.recv_packet.processed_bytes = suffix_position + suffix_bytes; 00047 else 00048 { 00049 connector_debug_printf("sm_verify_sms_preamble: valid_prefix=%d, valid_shared_key=%d, valid_suffix=%d\n", valid_prefix, valid_shared_key, valid_suffix); 00050 connector_debug_printf("%s\n",(char *)data_ptr); 00051 00052 result = connector_invalid_response; 00053 } 00054 } 00055 00056 return result; 00057 } 00058 #endif 00059 00060 #if (defined CONNECTOR_TRANSPORT_UDP) 00061 static connector_status_t sm_verify_udp_header(connector_sm_data_t * const sm_ptr) 00062 { 00063 connector_status_t result = connector_invalid_response; 00064 connector_sm_packet_t * const recv_ptr = &sm_ptr->network.recv_packet; 00065 uint8_t * data_ptr = recv_ptr->data; 00066 uint8_t const version_and_type = *data_ptr++; 00067 uint8_t const version = version_and_type >> 4; 00068 connector_sm_id_type_t const type = (connector_sm_id_type_t)(version_and_type & 0x0F); 00069 00070 if (version != SM_UDP_VERSION) 00071 { 00072 connector_debug_printf("sm_verify_udp_header: invalid SM UDP version [%d]\n", version); 00073 result = connector_abort; 00074 goto error; 00075 } 00076 00077 if (type != sm_ptr->transport.id_type) 00078 goto done; 00079 00080 if (memcmp(data_ptr, sm_ptr->transport.id, sm_ptr->transport.id_length)) 00081 goto done; /* not for us */ 00082 00083 recv_ptr->processed_bytes = sm_ptr->transport.id_length + 1; 00084 result = connector_working; 00085 00086 done: 00087 error: 00088 return result; 00089 } 00090 #endif 00091 00092 #if (defined CONNECTOR_SM_MULTIPART) 00093 static connector_status_t sm_multipart_allocate(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session) 00094 { 00095 connector_status_t status = connector_working; 00096 size_t const max_payload_bytes = sm_get_max_payload_bytes(sm_ptr); 00097 size_t const max_session_bytes = (((max_payload_bytes * session->segments.count) + 3)/4) * 4; /* make sure it is word aligned */ 00098 size_t const size_array_bytes = sizeof(*session->segments.size_array) * session->segments.count; 00099 00100 ASSERT_GOTO(session->in.data == NULL, error); 00101 session->in.bytes = max_session_bytes + size_array_bytes; 00102 status = sm_allocate_user_buffer(connector_ptr, &session->in); 00103 ASSERT_GOTO(status == connector_working, error); 00104 session->segments.size_array = (void *)(session->in.data + max_session_bytes); /* alignment issue is taken care where max_session_bytes is defined */ 00105 memset(session->segments.size_array, 0, size_array_bytes); 00106 00107 error: 00108 return status; 00109 } 00110 #endif 00111 00112 static connector_status_t sm_more_data_callback(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr) 00113 { 00114 connector_status_t result; 00115 connector_request_id_t request_id; 00116 connector_callback_status_t callback_status; 00117 connector_sm_more_data_t cb_data; 00118 00119 cb_data.transport = sm_ptr->network.transport; 00120 request_id.sm_request = connector_request_id_sm_more_data; 00121 callback_status = connector_callback(connector_ptr->callback, connector_class_id_short_message, request_id, &cb_data); 00122 result = sm_map_callback_status_to_connector_status(callback_status); 00123 00124 return result; 00125 } 00126 00127 typedef struct 00128 { 00129 uint32_t request_id; 00130 size_t bytes; 00131 00132 connector_bool_t isRequest; 00133 connector_bool_t isResponseNeeded; 00134 connector_bool_t isPackCmd; 00135 connector_bool_t isMultipart; 00136 connector_bool_t isCompressed; 00137 connector_bool_t isError; 00138 00139 connector_sm_cmd_t command; 00140 00141 enum 00142 { 00143 sm_single_segment, 00144 sm_multipart_first_segment, 00145 sm_multipart_subsequent_segment 00146 } type; 00147 00148 struct 00149 { 00150 uint8_t count; 00151 uint8_t number; 00152 } segment; 00153 00154 uint16_t crc16; 00155 uint8_t cmd_status; 00156 } sm_header_t; 00157 00158 static connector_status_t sm_process_header(connector_sm_packet_t * const recv_ptr, sm_header_t * const header) 00159 { 00160 connector_status_t result = connector_invalid_payload_packet; 00161 uint8_t * data_ptr = &recv_ptr->data[recv_ptr->processed_bytes]; 00162 uint8_t * const segment = data_ptr; 00163 00164 header->segment.count = 1; 00165 header->segment.number = 0; 00166 header->bytes = 0; 00167 header->command = connector_sm_cmd_opaque_response; 00168 header->isError = connector_false; 00169 header->isCompressed = connector_false; 00170 00171 { 00172 uint8_t const info_field = message_load_u8(segment, info); 00173 uint8_t const request_id_high_bits_mask = 0x03; 00174 00175 header->request_id = (info_field & request_id_high_bits_mask) << 8; 00176 header->request_id |= message_load_u8(segment, request); 00177 00178 header->isMultipart = SmIsMultiPart(info_field); 00179 header->isRequest = SmIsRequest(info_field); 00180 header->isResponseNeeded = SmIsResponseNeeded(info_field); 00181 } 00182 00183 if (header->isMultipart) 00184 { 00185 #if (defined CONNECTOR_SM_MULTIPART) 00186 { 00187 uint8_t * const segment0 = data_ptr; 00188 00189 header->segment.number = message_load_u8(segment0, segment); 00190 if (header->segment.number > 0) 00191 { 00192 uint8_t * const segmentn = data_ptr; 00193 00194 header->cmd_status = 0; 00195 header->type = sm_multipart_subsequent_segment; 00196 00197 if (header->isPackCmd) 00198 { 00199 header->bytes = record_end(segmentn) - sizeof header->crc16; 00200 } 00201 else 00202 { 00203 header->crc16 = message_load_be16(segmentn, crc); 00204 message_store_be16(segmentn, crc, 0); 00205 header->bytes = record_end(segmentn); 00206 } 00207 } 00208 else 00209 { 00210 header->type = sm_multipart_first_segment; 00211 header->segment.count = message_load_u8(segment0, count); 00212 header->cmd_status = message_load_u8(segment0, cmd_status); 00213 00214 if (header->isPackCmd) 00215 { 00216 header->bytes = record_end(segment0) - sizeof header->crc16; 00217 } 00218 else 00219 { 00220 header->crc16 = message_load_be16(segment0, crc); 00221 message_store_be16(segment0, crc, 0); 00222 header->bytes = record_end(segment0); 00223 } 00224 } 00225 } 00226 #else 00227 { 00228 connector_debug_printf("Received multipart packet, but multipart is disabled\n"); 00229 connector_debug_printf("Review CONNECTOR_SM_MULTIPART and CONNECTOR_SM_MAX_RX_SEGMENTS defines\n"); 00230 goto error; 00231 } 00232 #endif 00233 } 00234 else 00235 { 00236 header->cmd_status = message_load_u8(segment, cmd_status); 00237 if (header->isPackCmd) 00238 { 00239 header->bytes = record_end(segment) - sizeof header->crc16; 00240 } 00241 else 00242 { 00243 header->crc16 = message_load_be16(segment, crc); 00244 message_store_be16(segment, crc, 0); 00245 header->bytes = record_end(segment); 00246 } 00247 } 00248 00249 header->isCompressed = SmIsCompressed(header->cmd_status); 00250 #if !(defined CONNECTOR_COMPRESSION) 00251 if (header->isCompressed) 00252 { 00253 connector_debug_printf("sm_process_header: Received compressed packet, but compression is disabled!\n"); 00254 goto error; 00255 } 00256 #endif 00257 00258 if (header->isRequest) 00259 { 00260 header->command = (connector_sm_cmd_t)(header->cmd_status & 0x7F); 00261 if (header->isPackCmd && (header->command == connector_sm_cmd_pack)) 00262 { 00263 connector_debug_printf("sm_process_header: Pack command inside a pack command is not allowed!\n"); 00264 goto error; 00265 } 00266 header->isError = connector_false; 00267 } 00268 else 00269 { 00270 header->isError = SmIsError(header->cmd_status); 00271 header->command = connector_sm_cmd_opaque_response; 00272 } 00273 00274 if (!header->isPackCmd) 00275 { 00276 size_t const sm_bytes = recv_ptr->total_bytes - recv_ptr->processed_bytes; 00277 uint16_t calculated_crc = 0; 00278 00279 calculated_crc = sm_calculate_crc16(calculated_crc, data_ptr, sm_bytes); 00280 if(calculated_crc != header->crc16) 00281 { 00282 connector_debug_printf("sm_process_header: crc error!\n"); 00283 goto error; 00284 } 00285 00286 if (header->isRequest) 00287 header->isPackCmd = connector_bool(header->command == connector_sm_cmd_pack); 00288 } 00289 00290 recv_ptr->processed_bytes += header->bytes; 00291 result = connector_working; 00292 00293 error: 00294 return result; 00295 } 00296 00297 static connector_status_t sm_update_session(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, 00298 sm_header_t * const header, size_t const payload_bytes) 00299 { 00300 connector_status_t result = connector_invalid_payload_packet; 00301 connector_sm_packet_t * const recv_ptr = &sm_ptr->network.recv_packet; 00302 connector_bool_t const client_originated = connector_bool(!header->isRequest); 00303 connector_sm_session_t * session = get_sm_session(sm_ptr, header->request_id, client_originated); 00304 00305 if (session == NULL) 00306 { 00307 session = sm_create_session(connector_ptr, sm_ptr, connector_false); 00308 if (session == NULL) 00309 { 00310 result = connector_pending; 00311 goto error; 00312 } 00313 00314 session->request_id = header->request_id; 00315 session->command = client_originated ? connector_sm_cmd_opaque_response : header->command; 00316 } 00317 00318 if (header->segment.number == 0) 00319 { 00320 if (header->isCompressed) SmSetCompressed(session->flags); 00321 00322 if (header->isRequest) 00323 { 00324 if (header->isResponseNeeded) SmSetResponseNeeded(session->flags); 00325 /* If the first segment of a multipart SMS that arrived was not segment0, previously stored session->command information is wrong as 00326 * for multipart messages, type is only included in the 0th segment. Update it here */ 00327 session->command = header->command; 00328 } 00329 else if (header->isError) 00330 { 00331 uint16_t const error_value = LoadBE16(&recv_ptr->data[recv_ptr->processed_bytes]); 00332 00333 switch (error_value) 00334 { 00335 case connector_sm_error_in_request: 00336 session->error = connector_sm_error_in_request; 00337 break; 00338 00339 case connector_sm_error_unavailable: 00340 session->error = connector_sm_error_unavailable; 00341 break; 00342 00343 default: 00344 session->error = connector_sm_error_unknown; 00345 break; 00346 } 00347 00348 SmSetError(session->flags); 00349 recv_ptr->processed_bytes += sizeof error_value; 00350 } 00351 00352 session->segments.count = header->segment.count; 00353 } 00354 00355 #if (defined CONNECTOR_SM_MULTIPART) 00356 if (header->isMultipart) 00357 { 00358 SmSetMultiPart(session->flags); 00359 if (session->in.data == NULL) 00360 { 00361 if (header->segment.number > 0) 00362 session->segments.count = sm_ptr->session.max_segments; 00363 00364 result = sm_multipart_allocate(connector_ptr, sm_ptr, session); 00365 ASSERT_GOTO(result == connector_working, error); 00366 ASSERT_GOTO(session->in.data != NULL, error); 00367 } 00368 00369 if (session->segments.size_array[header->segment.number] == 0) 00370 { 00371 size_t const max_payload_bytes = sm_get_max_payload_bytes(sm_ptr); 00372 uint8_t * copy_to = session->in.data + (header->segment.number * max_payload_bytes); 00373 00374 session->segments.size_array[header->segment.number] = payload_bytes; 00375 memcpy(copy_to, &recv_ptr->data[recv_ptr->processed_bytes], payload_bytes); 00376 session->segments.processed++; 00377 } 00378 else 00379 { 00380 connector_debug_printf("sm_update_session: duplicate segment %d, in id %d\n", header->segment.number, session->request_id); 00381 } 00382 } 00383 else 00384 #endif 00385 { 00386 session->in.bytes = payload_bytes; 00387 if (payload_bytes > 0) 00388 { 00389 result = sm_allocate_user_buffer(connector_ptr, &session->in); 00390 ASSERT_GOTO(result == connector_working, error); 00391 memcpy(session->in.data, &recv_ptr->data[recv_ptr->processed_bytes], payload_bytes); 00392 } 00393 else 00394 session->in.data = NULL; 00395 session->segments.processed++; 00396 } 00397 00398 if (session->segments.processed >= session->segments.count) 00399 { 00400 session->bytes_processed = 0; 00401 session->segments.processed = 0; 00402 session->sm_state = connector_sm_state_process_payload; 00403 00404 #if (defined CONNECTOR_COMPRESSION) 00405 if (SmIsCompressed(session->flags)) 00406 { 00407 session->compress.out.data = NULL; 00408 session->sm_state = connector_sm_state_decompress; 00409 } 00410 #endif 00411 } 00412 00413 recv_ptr->processed_bytes += payload_bytes; 00414 result = connector_working; 00415 00416 error: 00417 return result; 00418 } 00419 00420 static connector_status_t sm_process_packet(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr) 00421 { 00422 sm_header_t sm_header; 00423 connector_status_t result; 00424 connector_sm_packet_t * const recv_ptr = &sm_ptr->network.recv_packet; 00425 size_t sm_bytes = recv_ptr->total_bytes - recv_ptr->processed_bytes; 00426 00427 sm_header.isPackCmd = connector_false; 00428 sm_header.crc16 = 0; 00429 do 00430 { 00431 result = sm_process_header(recv_ptr, &sm_header); 00432 if (result != connector_working) goto error; 00433 00434 if ((sm_header.segment.count > sm_ptr->session.max_segments) || (sm_header.segment.number >= sm_ptr->session.max_segments)) 00435 { 00436 connector_debug_printf("sm_process_packet: Exceeded maximum segments [%" PRIsize "/%" PRIsize "]!\n", sm_header.segment.count, sm_ptr->session.max_segments); 00437 connector_debug_printf("Review CONNECTOR_SM_MULTIPART and CONNECTOR_SM_MAX_RX_SEGMENTS defines\n"); 00438 goto error; 00439 } 00440 00441 if (sm_header.command == connector_sm_cmd_pack) 00442 { 00443 enum sm_pack_t 00444 { 00445 field_define(pack_header, flag, uint8_t), 00446 field_define(pack_header, length, uint16_t), 00447 record_end(pack_header) 00448 }; 00449 uint8_t * const pack_header = &recv_ptr->data[recv_ptr->processed_bytes]; 00450 uint8_t const flag = message_load_u8(pack_header, flag); 00451 00452 #define SM_MESSAGE_PENDING 0x01 00453 if ((flag & SM_MESSAGE_PENDING) == SM_MESSAGE_PENDING) 00454 { 00455 result = sm_more_data_callback(connector_ptr, sm_ptr); 00456 if (result != connector_working) goto error; 00457 } 00458 #undef SM_MESSAGE_PENDING 00459 00460 sm_bytes = message_load_be16(pack_header, length); 00461 recv_ptr->processed_bytes += record_end(pack_header); 00462 continue; 00463 } 00464 00465 { 00466 size_t const payload_bytes = sm_bytes - sm_header.bytes; 00467 00468 ASSERT(sm_bytes >= sm_header.bytes); 00469 result = sm_update_session(connector_ptr, sm_ptr, &sm_header, payload_bytes); 00470 } 00471 00472 if (!sm_header.isPackCmd) break; 00473 00474 { 00475 size_t const sm_header_size = 5; 00476 size_t const remaining_bytes = recv_ptr->total_bytes - recv_ptr->processed_bytes; 00477 00478 if (remaining_bytes < sm_header_size) break; 00479 } 00480 00481 sm_bytes = LoadBE16(&recv_ptr->data[recv_ptr->processed_bytes]); 00482 recv_ptr->processed_bytes += sizeof(uint16_t); 00483 00484 } while (recv_ptr->processed_bytes < recv_ptr->total_bytes); 00485 00486 result = connector_working; 00487 00488 error: 00489 if (result == connector_invalid_payload_packet) /* unreliable method, so silently ignore the packet */ 00490 result = connector_working; 00491 00492 recv_ptr->total_bytes = 0; 00493 recv_ptr->processed_bytes = 0; 00494 00495 return result; 00496 } 00497 00498 static connector_status_t sm_receive_data(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr) 00499 { 00500 connector_status_t result = connector_pending; 00501 connector_sm_packet_t * const recv_ptr = &sm_ptr->network.recv_packet; 00502 connector_callback_status_t status; 00503 connector_request_id_t request_id; 00504 connector_network_receive_t read_data; 00505 00506 if (recv_ptr->total_bytes > 0) goto done; 00507 00508 read_data.handle = sm_ptr->network.handle; 00509 read_data.buffer = recv_ptr->data; 00510 read_data.bytes_available = sm_ptr->transport.mtu; 00511 read_data.bytes_used = 0; 00512 00513 request_id.network_request = connector_request_id_network_receive; 00514 status = connector_callback(connector_ptr->callback, sm_ptr->network.class_id, request_id, &read_data); 00515 ASSERT(status != connector_callback_unrecognized); 00516 switch (status) 00517 { 00518 case connector_callback_busy: 00519 result = connector_idle; 00520 goto done; 00521 00522 case connector_callback_continue: 00523 recv_ptr->total_bytes = read_data.bytes_used; 00524 recv_ptr->processed_bytes = 0; 00525 00526 switch (sm_ptr->network.transport) 00527 { 00528 #if (defined CONNECTOR_TRANSPORT_SMS) 00529 case connector_transport_sms: 00530 result = sm_verify_sms_preamble(sm_ptr); 00531 switch(result) 00532 { 00533 case connector_working: 00534 break; 00535 case connector_invalid_response: 00536 /* not Device Cloud packet? Ignore the packet */ 00537 recv_ptr->total_bytes = 0; 00538 recv_ptr->processed_bytes = 0; 00539 result = connector_working; 00540 goto done; 00541 default: 00542 goto done; 00543 } 00544 00545 result = sm_decode_segment(connector_ptr, recv_ptr); 00546 00547 /* Remove sms preamble */ 00548 sm_ptr->network.recv_packet.processed_bytes = 0; 00549 00550 break; 00551 #endif 00552 00553 #if (defined CONNECTOR_TRANSPORT_UDP) 00554 case connector_transport_udp: 00555 result = sm_verify_udp_header(sm_ptr); 00556 break; 00557 #endif 00558 00559 default: 00560 ASSERT_GOTO(connector_false, done); 00561 break; 00562 } 00563 00564 if(result != connector_working) goto done; /* not Device Cloud packet? */ 00565 result = sm_process_packet(connector_ptr, sm_ptr); 00566 break; 00567 00568 case connector_callback_abort: 00569 result = connector_abort; 00570 break; 00571 00572 default: 00573 connector_debug_printf("sm_receive_data: callback returned error [%d]\n", status); 00574 result = connector_device_error; 00575 break; 00576 } 00577 00578 sm_verify_result(sm_ptr, &result); 00579 00580 done: 00581 return result; 00582 } 00583 00584 #if (defined CONNECTOR_COMPRESSION) 00585 static connector_status_t sm_decompress_data(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session) 00586 { 00587 connector_status_t status = connector_working; 00588 size_t const max_payload_bytes = sm_get_max_payload_bytes(sm_ptr); 00589 uint8_t zlib_header[] = {0x58, 0xC3}; 00590 z_streamp const zlib_ptr = &session->compress.zlib; 00591 int zret; 00592 00593 if (session->compress.out.data == NULL) 00594 { 00595 session->compress.out.bytes = max_payload_bytes; 00596 status = sm_allocate_user_buffer(connector_ptr, &session->compress.out); 00597 ASSERT_GOTO(status == connector_working, done); 00598 00599 memset(zlib_ptr, 0, sizeof *zlib_ptr); 00600 zret = inflateInit(zlib_ptr); 00601 ASSERT_GOTO(zret == Z_OK, error); 00602 zlib_ptr->next_out = session->compress.out.data; 00603 zlib_ptr->avail_out = session->compress.out.bytes; 00604 zlib_ptr->next_in = zlib_header; 00605 zlib_ptr->avail_in = sizeof zlib_header; 00606 } 00607 00608 while (zlib_ptr->avail_out > 0) 00609 { 00610 if (zlib_ptr->avail_in == 0) 00611 { 00612 if (session->segments.processed == session->segments.count) 00613 { 00614 SmSetLastData(session->flags); 00615 break; 00616 } 00617 else 00618 { 00619 size_t const data_index = session->segments.processed * max_payload_bytes; 00620 00621 zlib_ptr->next_in = &session->in.data[data_index]; 00622 zlib_ptr->avail_in = SmIsMultiPart(session->flags) ? session->segments.size_array[session->segments.processed] : session->in.bytes; 00623 session->segments.processed++; 00624 } 00625 } 00626 00627 zret = inflate(zlib_ptr, Z_NO_FLUSH); 00628 switch(zret) 00629 { 00630 case Z_STREAM_END: 00631 case Z_BUF_ERROR: 00632 case Z_OK: 00633 break; 00634 00635 default: 00636 status = connector_abort; 00637 connector_debug_printf("ZLIB Return value [%d]\n", zret); 00638 ASSERT_GOTO(connector_false, error); 00639 break; 00640 } 00641 } 00642 00643 { 00644 size_t const payload_bytes = session->compress.out.bytes - zlib_ptr->avail_out; 00645 00646 status = sm_pass_user_data(connector_ptr, session, session->compress.out.data, payload_bytes); 00647 switch (status) 00648 { 00649 case connector_pending: 00650 goto done; 00651 00652 case connector_working: 00653 if (SmIsNotLastData(session->flags)) 00654 { 00655 zlib_ptr->next_out = session->compress.out.data; 00656 zlib_ptr->avail_out = session->compress.out.bytes; 00657 goto done; 00658 } 00659 break; 00660 00661 default: 00662 break; 00663 } 00664 } 00665 00666 error: 00667 zret = inflateEnd(zlib_ptr); 00668 ASSERT(zret == Z_OK); 00669 00670 if (status != connector_abort) 00671 { 00672 status = free_data_buffer(connector_ptr, named_buffer_id(sm_data_block), session->compress.out.data); 00673 session->compress.out.data = NULL; 00674 } 00675 00676 done: 00677 return status; 00678 } 00679 #endif 00680 00681 static connector_status_t sm_handle_error(connector_data_t * const connector_ptr, connector_sm_session_t * const session) 00682 { 00683 connector_status_t result = connector_working; 00684 connector_sm_state_t next_state = connector_sm_state_complete; 00685 00686 if (SmIsCloudOwned(session->flags) && SmIsRequest(session->flags)) 00687 next_state = connector_sm_state_send_data; 00688 00689 SmSetError(session->flags); 00690 if (session->user.context != NULL) /* let the user know */ 00691 { 00692 result = sm_inform_session_complete(connector_ptr, session); 00693 if (result != connector_working) goto error; 00694 } 00695 00696 result = sm_switch_path(connector_ptr, session, next_state); 00697 00698 error: 00699 return result; 00700 } 00701 00702 static connector_status_t sm_handle_complete(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session) 00703 { 00704 connector_status_t result = connector_working; 00705 00706 if (session->in.data != NULL) 00707 { 00708 result = free_data_buffer(connector_ptr, named_buffer_id(sm_data_block), session->in.data); 00709 if (result != connector_working) goto error; 00710 } 00711 00712 if (SmIsReboot(session->flags)) 00713 result = sm_process_reboot(connector_ptr); 00714 00715 switch(result) 00716 { 00717 case connector_abort: 00718 /* Keep connector_abort as the result */ 00719 sm_delete_session(connector_ptr, sm_ptr, session); 00720 break; 00721 case connector_pending: 00722 break; 00723 default: 00724 result = sm_delete_session(connector_ptr, sm_ptr, session); 00725 } 00726 00727 error: 00728 return result; 00729 } 00730 00731 static connector_status_t sm_process_recv_path(connector_data_t * const connector_ptr, connector_sm_data_t * const sm_ptr, connector_sm_session_t * const session) 00732 { 00733 connector_status_t result = connector_abort; 00734 00735 ASSERT_GOTO(session != NULL, error); 00736 switch (session->sm_state) 00737 { 00738 case connector_sm_state_receive_data: 00739 if (sm_ptr->timeout_in_seconds != SM_WAIT_FOREVER) 00740 { 00741 unsigned long current_time = 0; 00742 00743 result = get_system_time(connector_ptr, ¤t_time); 00744 ASSERT_GOTO(result == connector_working, error); 00745 if (current_time > (session->start_time + sm_ptr->timeout_in_seconds)) 00746 { 00747 session->sm_state = connector_sm_state_error; 00748 session->error = connector_sm_error_timeout; 00749 connector_debug_printf("Sm session [%u] timeout... start time:%u, current time:%u\n", session->request_id, session->start_time, current_time); 00750 } 00751 } 00752 00753 result = connector_idle; /* still receiving data, handled in sm_receive_data() */ 00754 break; 00755 00756 #if (defined CONNECTOR_COMPRESSION) 00757 case connector_sm_state_decompress: 00758 result = sm_decompress_data(connector_ptr, sm_ptr, session); 00759 break; 00760 #endif 00761 00762 case connector_sm_state_process_payload: 00763 result = sm_process_payload(connector_ptr, sm_ptr, session); 00764 break; 00765 00766 case connector_sm_state_complete: 00767 result = sm_handle_complete(connector_ptr, sm_ptr, session); 00768 break; 00769 00770 case connector_sm_state_error: 00771 result = sm_handle_error(connector_ptr, session); 00772 break; 00773 00774 default: 00775 ASSERT(connector_false); 00776 break; 00777 } 00778 00779 sm_verify_result(sm_ptr, &result); 00780 00781 error: 00782 return result; 00783 } 00784
Generated on Tue Jul 12 2022 19:18:38 by
1.7.2