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_data_service.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 typedef enum 00014 { 00015 data_service_opcode_put_request, 00016 data_service_opcode_put_response, 00017 data_service_opcode_device_request, 00018 data_service_opcode_device_response 00019 } data_service_opcode_t; 00020 00021 typedef struct 00022 { 00023 void * callback_context; 00024 connector_request_data_service_send_t const * header; 00025 connector_bool_t dp_request; 00026 connector_request_id_data_service_t request_type; 00027 } data_service_context_t; 00028 00029 static void set_data_service_error(msg_service_request_t * const service_request, connector_session_error_t const error_code) 00030 { 00031 service_request->error_value = error_code; 00032 service_request->service_type = msg_service_type_error; 00033 } 00034 00035 00036 static connector_status_t call_ds_receive_callback(connector_data_t * const connector_ptr, 00037 data_service_context_t * const data_service, 00038 void * const data) 00039 { 00040 connector_status_t result = connector_working; 00041 connector_request_id_t request_id; 00042 00043 request_id.data_service_request = data_service->request_type; 00044 switch (request_id.data_service_request) 00045 { 00046 case connector_request_id_data_service_receive_reply_length: 00047 request_id.data_service_request = connector_request_id_data_service_receive_reply_data; 00048 /* fall thru for error (not-handle) response data */ 00049 case connector_request_id_data_service_receive_target: 00050 case connector_request_id_data_service_receive_data: 00051 case connector_request_id_data_service_receive_status: 00052 case connector_request_id_data_service_receive_reply_data: 00053 { 00054 connector_callback_status_t const status = connector_callback(connector_ptr->callback, connector_class_id_data_service, request_id, data); 00055 switch (status) 00056 { 00057 case connector_callback_continue: 00058 break; 00059 case connector_callback_error: 00060 data_service->request_type = connector_request_id_data_service_receive_reply_length; 00061 break; 00062 case connector_callback_busy: 00063 result = connector_pending; 00064 break; 00065 default: 00066 result = connector_abort; 00067 break; 00068 00069 } 00070 break; 00071 } 00072 00073 default: 00074 ASSERT(connector_false); 00075 break; 00076 } 00077 00078 return result; 00079 } 00080 00081 static connector_status_t process_ds_receive_target(connector_data_t * const connector_ptr, 00082 data_service_context_t * const data_service, 00083 uint8_t const * const data, 00084 size_t * const data_length) 00085 { 00086 /* 1st message so let's parse message-start packet: 00087 * 00088 * Data Service Device request format: 00089 * ------------------------------------------------------------------------------------------------------- 00090 * | 0 | 1 | 2+N | +1 | +1 | +1 | +M | ... | +P | 00091 * ------------------------------------------------------------------------------------------------------- 00092 * | Opcode | Target | Target | Parameter | Parameter 1 | Parameter 1 | Parameter 1 | Additional | Payload | 00093 * | | length | string | count | ID | data length | data | parameters | | 00094 * ------------------------------------------------------------------------------------------------------- 00095 * 00096 */ 00097 enum { 00098 field_define(ds_device_request, opcode, uint8_t), 00099 field_define(ds_device_request, target_length, uint8_t), 00100 record_end(ds_device_request_header) 00101 }; 00102 00103 enum { 00104 field_define(ds_device_request, parameter_count, uint8_t) 00105 }; 00106 00107 enum { 00108 field_define(ds_device_request, parameter_id, uint8_t), 00109 field_define(ds_device_request, parameter_length, uint8_t), 00110 record_end(ds_device_request_parameter) 00111 }; 00112 00113 connector_status_t result = connector_working; 00114 uint8_t const * ds_device_request = data; 00115 00116 char * target_string = NULL; 00117 uint8_t const target_length = message_load_u8(ds_device_request, target_length); 00118 00119 size_t const min_data_length = (size_t)(target_length + 00120 record_bytes(ds_device_request_header) + 00121 field_named_data(ds_device_request, parameter_count, size)); 00122 00123 ASSERT_GOTO((message_load_u8(ds_device_request, opcode) == data_service_opcode_device_request), done); 00124 ASSERT_GOTO(*data_length >= min_data_length, done); 00125 00126 ds_device_request += record_bytes(ds_device_request_header); 00127 00128 target_string = (char *)ds_device_request; 00129 ds_device_request += target_length; 00130 00131 { 00132 /* TODO: Parse and process each parameter in the future. 00133 * Ignore all parameters now. 00134 */ 00135 00136 uint8_t const parameter_count = message_load_u8(ds_device_request, parameter_count); 00137 uint8_t i; 00138 00139 ds_device_request += field_named_data(ds_device_request, parameter_count, size); 00140 00141 for (i=0; i < parameter_count; i++) 00142 { 00143 unsigned int const parameter_length = message_load_u8(ds_device_request, parameter_length); 00144 size_t const min_parameter_length = min_data_length + record_bytes(ds_device_request_parameter) + parameter_length; 00145 ASSERT_GOTO(*data_length >= min_parameter_length, done); 00146 00147 ds_device_request += record_bytes(ds_device_request_parameter); /* skip id and length */ 00148 ds_device_request += parameter_length; 00149 00150 } 00151 } 00152 00153 *data_length = (ds_device_request - data); 00154 00155 /* Add NUL to the target string. Must NULL-terminate it after parsing all parameters. 00156 * The NUL char is on parameter_count field in the request. 00157 */ 00158 target_string[target_length] = '\0'; 00159 00160 switch (data_service->request_type) 00161 { 00162 case connector_request_id_data_service_receive_target: 00163 { 00164 00165 connector_data_service_receive_target_t device_request; 00166 00167 device_request.transport = connector_transport_tcp; 00168 device_request.user_context = data_service->callback_context; 00169 device_request.target = target_string; 00170 device_request.response_required = connector_true; 00171 00172 result = call_ds_receive_callback(connector_ptr, data_service, &device_request); 00173 data_service->callback_context = device_request.user_context; 00174 break; 00175 } 00176 default: 00177 /* just skip the header and return */ 00178 break; 00179 } 00180 00181 done: 00182 return result; 00183 } 00184 00185 static connector_status_t process_ds_receive_data(connector_data_t * const connector_ptr, 00186 data_service_context_t * const data_service, 00187 uint8_t const * const data, 00188 size_t const data_length, 00189 unsigned int const flags) 00190 { 00191 connector_status_t result; 00192 00193 connector_data_service_receive_data_t device_request; 00194 device_request.transport = connector_transport_tcp; 00195 device_request.user_context = data_service->callback_context; 00196 device_request.buffer = data; 00197 device_request.bytes_used = data_length; 00198 device_request.more_data = MsgIsLastData(flags) ? connector_false : connector_true; 00199 00200 result = call_ds_receive_callback(connector_ptr, data_service, &device_request); 00201 data_service->callback_context = device_request.user_context; 00202 00203 return result; 00204 } 00205 static connector_status_t process_data_service_device_request(connector_data_t * const connector_ptr, 00206 msg_service_request_t * const service_request) 00207 { 00208 connector_status_t result = connector_working; 00209 msg_session_t * const session = service_request->session; 00210 data_service_context_t * data_service = session->service_context; 00211 msg_service_data_t * const service_data = service_request->have_data; 00212 00213 uint8_t const * ds_device_request = service_data->data_ptr; 00214 size_t ds_device_request_length = service_data->length_in_bytes; 00215 00216 connector_bool_t const isFirstRequest = connector_bool(MsgIsStart(service_data->flags)); 00217 00218 if (isFirstRequest) 00219 { 00220 if (data_service == NULL) 00221 { 00222 /* 1st time here so let's allocate service context memory for device request service */ 00223 void * ptr; 00224 00225 result = malloc_data_buffer(connector_ptr, sizeof *data_service, named_buffer_id(msg_service), &ptr); 00226 if (result != connector_working) 00227 { 00228 goto done; 00229 } 00230 00231 data_service = ptr; 00232 session->service_context = data_service; 00233 data_service->callback_context = NULL; 00234 data_service->dp_request = connector_false; 00235 data_service->request_type = connector_request_id_data_service_receive_target; 00236 } 00237 } 00238 00239 switch (data_service->request_type) 00240 { 00241 case connector_request_id_data_service_receive_target: 00242 ds_device_request_length = service_data->length_in_bytes; 00243 00244 result = process_ds_receive_target(connector_ptr, data_service, ds_device_request, &ds_device_request_length); 00245 00246 switch (result) 00247 { 00248 case connector_working: 00249 if (data_service->request_type == connector_request_id_data_service_receive_target) 00250 data_service->request_type = connector_request_id_data_service_receive_data; 00251 /* make it return busy so it comes here to skip parsing the header for the 1st data block */ 00252 result = connector_pending; 00253 break; 00254 default: 00255 break; 00256 } 00257 break; 00258 00259 case connector_request_id_data_service_receive_data: 00260 if (isFirstRequest) 00261 { 00262 /* skip the header; just get the point to data */ 00263 result = process_ds_receive_target(connector_ptr, data_service, ds_device_request, &ds_device_request_length); 00264 if (result != connector_working) goto done; 00265 ds_device_request += ds_device_request_length; 00266 } 00267 { 00268 size_t const data_length = (size_t)(ds_device_request - (uint8_t *)service_data->data_ptr); 00269 ds_device_request_length = service_data->length_in_bytes - data_length; 00270 00271 result = process_ds_receive_data(connector_ptr, data_service, ds_device_request, ds_device_request_length, service_data->flags); 00272 switch (result) 00273 { 00274 case connector_working: 00275 /* data_service->request_type may have been changed inside process_ds_receive_data() */ 00276 switch (data_service->request_type) 00277 { 00278 case connector_request_id_data_service_receive_reply_length: 00279 break; 00280 00281 default: 00282 if (MsgIsLastData(service_data->flags)) 00283 data_service->request_type = connector_request_id_data_service_receive_reply_data; 00284 break; 00285 } 00286 break; 00287 default: 00288 break; 00289 } 00290 break; 00291 } 00292 case connector_request_id_data_service_receive_reply_length: 00293 /* We set this when callback returns error. 00294 * We need to respond with an error after receiving all request data. 00295 */ 00296 break; 00297 00298 default: 00299 ASSERT(connector_false); 00300 goto done; 00301 } 00302 00303 done: 00304 return result; 00305 } 00306 00307 static connector_status_t process_data_service_device_response(connector_data_t * const connector_ptr, 00308 msg_service_request_t * const service_request) 00309 { 00310 /* Data Service Device response format: 00311 * --------------------------------- 00312 * | 0 | 1 | 2... | 00313 * --------------------------------- 00314 * | Opcode | status | Response Data | 00315 * --------------------------------- 00316 */ 00317 enum { 00318 field_define(ds_device_response, opcode, uint8_t), 00319 field_define(ds_device_response, status, uint8_t), 00320 record_end(ds_device_response_header) 00321 }; 00322 00323 connector_status_t result = connector_working; 00324 msg_service_data_t * const service_data = service_request->need_data; 00325 msg_session_t * const session = service_request->session; 00326 data_service_context_t * const data_service = session->service_context; 00327 connector_bool_t const isFirstResponse = connector_bool(MsgIsStart(service_data->flags)); 00328 00329 /* save some room for response header on 1st response data */ 00330 size_t const header_length = isFirstResponse == connector_true ? record_bytes(ds_device_response_header) : 0; 00331 uint8_t * const data_ptr = service_data->data_ptr; 00332 00333 00334 connector_data_service_receive_reply_data_t device_request; 00335 00336 device_request.transport = connector_transport_tcp; 00337 device_request.user_context = data_service->callback_context; 00338 device_request.buffer = data_ptr + header_length; 00339 device_request.bytes_available = service_data->length_in_bytes - header_length; 00340 device_request.bytes_used = 0; 00341 device_request.more_data = connector_false; 00342 00343 { 00344 connector_request_id_data_service_t const request_type = data_service->request_type; 00345 00346 switch (request_type) 00347 { 00348 case connector_request_id_data_service_receive_reply_length: 00349 /* We got here because callback returns error for request data. 00350 * Just get the replay data. 00351 */ 00352 /* fall thru */ 00353 case connector_request_id_data_service_receive_reply_data: 00354 { 00355 00356 result = call_ds_receive_callback(connector_ptr, data_service, &device_request); 00357 data_service->callback_context = device_request.user_context; 00358 if (request_type != data_service->request_type && 00359 data_service->request_type == connector_request_id_data_service_receive_reply_length) 00360 { 00361 /* callback returns error on reply data 00362 * We need to cancel the message in messaging layer. 00363 */ 00364 device_request.bytes_used = 0; 00365 device_request.more_data = connector_false; 00366 set_data_service_error(service_request, connector_session_error_cancel); 00367 } 00368 break; 00369 } 00370 default: 00371 /* should be here */ 00372 ASSERT(connector_false); 00373 goto done; 00374 } 00375 } 00376 if (isFirstResponse) 00377 { 00378 00379 enum { 00380 connector_data_service_device_success, 00381 connector_data_service_device_not_handled 00382 }; 00383 00384 /* Add header for 1st response message */ 00385 uint8_t * const ds_device_response = service_data->data_ptr; 00386 uint8_t const target_status = (data_service->request_type == connector_request_id_data_service_receive_reply_length) ? 00387 connector_data_service_device_not_handled: connector_data_service_device_success; 00388 00389 message_store_u8(ds_device_response, opcode, data_service_opcode_device_response); 00390 message_store_u8(ds_device_response, status, target_status); 00391 } 00392 00393 if (!device_request.more_data) 00394 { 00395 data_service->dp_request = connector_true; 00396 MsgSetLastData(service_data->flags); 00397 } 00398 service_data->length_in_bytes = device_request.bytes_used + header_length; 00399 00400 done: 00401 return result; 00402 } 00403 00404 00405 static connector_status_t process_data_service_device_error(connector_data_t * const connector_ptr, 00406 msg_service_request_t * const service_request) 00407 { 00408 connector_status_t result = connector_working; 00409 00410 msg_session_t * const session = service_request->session; 00411 data_service_context_t * const data_service = session->service_context; 00412 connector_data_service_status_t device_request; 00413 00414 00415 device_request.transport = connector_transport_tcp; 00416 device_request.user_context = data_service->callback_context; 00417 data_service->request_type = connector_request_id_data_service_receive_status; 00418 00419 switch (service_request->error_value) 00420 { 00421 case connector_session_error_none: 00422 device_request.status = connector_data_service_status_complete; 00423 break; 00424 00425 case connector_session_error_cancel: 00426 device_request.status = connector_data_service_status_cancel; 00427 break; 00428 00429 case connector_session_error_timeout: 00430 device_request.status = connector_data_service_status_timeout; 00431 break; 00432 00433 default: 00434 device_request.status = connector_data_service_status_session_error; 00435 device_request.session_error = service_request->error_value; 00436 break; 00437 } 00438 00439 result = call_ds_receive_callback(connector_ptr, data_service, &device_request); 00440 00441 data_service->callback_context = device_request.user_context; 00442 00443 return result; 00444 } 00445 00446 static connector_status_t data_service_device_request_callback(connector_data_t * const connector_ptr, msg_service_request_t * const service_request) 00447 { 00448 connector_status_t status = connector_working; 00449 00450 switch (service_request->service_type) 00451 { 00452 case msg_service_type_need_data: 00453 status = process_data_service_device_response(connector_ptr, service_request); 00454 break; 00455 00456 case msg_service_type_have_data: 00457 status = process_data_service_device_request(connector_ptr, service_request); 00458 break; 00459 00460 case msg_service_type_error: 00461 { 00462 msg_session_t * const session = service_request->session; 00463 session->error = service_request->error_value; 00464 status = process_data_service_device_error(connector_ptr, service_request); 00465 break; 00466 } 00467 00468 case msg_service_type_free: 00469 { 00470 msg_session_t * const session = service_request->session; 00471 #if (CONNECTOR_VERSION >= 0x02010000) 00472 if (session->error == connector_session_error_none) 00473 { 00474 /* If there is no error, call the user to inform that session is done */ 00475 status = process_data_service_device_error(connector_ptr, service_request); 00476 if (status != connector_working) 00477 break; 00478 } 00479 #endif 00480 status = free_data_buffer(connector_ptr, named_buffer_id(msg_service), session->service_context); 00481 break; 00482 } 00483 00484 default: 00485 ASSERT(connector_false); 00486 break; 00487 } 00488 00489 return status; 00490 } 00491 00492 static size_t fill_put_request_header(connector_request_data_service_send_t const * const request, uint8_t * const data) 00493 { 00494 uint8_t * ptr = data; 00495 00496 *ptr++ = data_service_opcode_put_request; 00497 00498 /* fill path */ 00499 if (request->path != NULL) 00500 { 00501 uint8_t const bytes = (uint8_t) strlen(request->path); 00502 00503 ASSERT(strlen(request->path) <= UCHAR_MAX); 00504 *ptr++ = bytes; 00505 memcpy(ptr, request->path, bytes); 00506 ptr += bytes; 00507 } 00508 00509 /* fill parameters */ 00510 { 00511 connector_bool_t const have_type = connector_bool(request->content_type != NULL); 00512 uint8_t const parameter_requested = 1; 00513 uint8_t params = have_type ? 1 : 0; 00514 00515 enum 00516 { 00517 parameter_id_content_type, 00518 parameter_id_archive, 00519 parameter_id_append, 00520 parameter_id_transient 00521 }; 00522 00523 if (request->option != connector_data_service_send_option_overwrite) params++; 00524 00525 *ptr++ = params; 00526 00527 if (have_type) 00528 { 00529 uint8_t const bytes = (uint8_t) strlen(request->content_type); 00530 00531 ASSERT(strlen(request->content_type) <= UCHAR_MAX); 00532 *ptr++ = parameter_id_content_type; 00533 *ptr++ = bytes; 00534 memcpy(ptr, request->content_type, bytes); 00535 ptr += bytes; 00536 } 00537 00538 switch(request->option) 00539 { 00540 case connector_data_service_send_option_archive: 00541 *ptr++ = parameter_id_archive; 00542 *ptr++ = parameter_requested; 00543 break; 00544 00545 case connector_data_service_send_option_append: 00546 *ptr++ = parameter_id_append; 00547 *ptr++ = parameter_requested; 00548 break; 00549 00550 case connector_data_service_send_option_transient: 00551 *ptr++ = parameter_id_transient; 00552 *ptr++ = parameter_requested; 00553 break; 00554 00555 default: 00556 break; 00557 } 00558 } 00559 00560 return (size_t)(ptr - data); 00561 } 00562 00563 static connector_status_t call_put_request_user(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, connector_request_id_data_service_t const request_id, void * const cb_data) 00564 { 00565 connector_status_t status = connector_working; 00566 msg_session_t * const session = service_request->session; 00567 data_service_context_t * const context = (session != NULL) ? session->service_context : NULL; 00568 connector_callback_status_t callback_status = connector_callback_continue; 00569 00570 if ((context == NULL) || (context->dp_request == connector_false)) 00571 { 00572 connector_request_id_t request; 00573 00574 request.data_service_request = request_id; 00575 callback_status = connector_callback(connector_ptr->callback, connector_class_id_data_service, request, cb_data); 00576 } 00577 #if (defined CONNECTOR_DATA_POINTS) 00578 else 00579 { 00580 callback_status = dp_handle_callback(connector_ptr, request_id, cb_data); 00581 } 00582 #endif 00583 00584 switch (callback_status) 00585 { 00586 case connector_callback_continue: 00587 status = connector_working; 00588 break; 00589 00590 case connector_callback_error: 00591 set_data_service_error(service_request, connector_session_error_cancel); 00592 status = connector_working; 00593 break; 00594 00595 case connector_callback_busy: 00596 status = connector_pending; 00597 break; 00598 00599 default: 00600 status = connector_abort; 00601 break; 00602 } 00603 00604 return status; 00605 } 00606 00607 static connector_status_t process_send_request(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, data_service_context_t * const ds_ptr) 00608 { 00609 connector_status_t status = connector_working; 00610 msg_service_data_t * const service_data = service_request->need_data; 00611 connector_data_service_send_data_t user_data; 00612 00613 user_data.transport = connector_transport_tcp; 00614 user_data.user_context = ds_ptr->callback_context; 00615 user_data.bytes_used = 0; 00616 user_data.more_data = connector_false; 00617 00618 if (MsgIsStart(service_data->flags)) 00619 { 00620 uint8_t * dptr = service_data->data_ptr; 00621 size_t const bytes = fill_put_request_header(ds_ptr->header, dptr); 00622 00623 if (bytes >= service_data->length_in_bytes) 00624 { 00625 connector_debug_printf("process_send_request: required bytes [%" PRIsize "] is more than available [%" PRIsize "]\n", bytes, service_data->length_in_bytes); 00626 goto error; 00627 } 00628 00629 user_data.buffer = dptr + bytes; 00630 user_data.bytes_available = service_data->length_in_bytes - bytes; 00631 service_data->length_in_bytes = bytes; 00632 } 00633 else 00634 { 00635 user_data.buffer = service_data->data_ptr; 00636 user_data.bytes_available = service_data->length_in_bytes; 00637 service_data->length_in_bytes = 0; 00638 } 00639 00640 status = call_put_request_user(connector_ptr, service_request, connector_request_id_data_service_send_data, &user_data); 00641 if (status == connector_working) 00642 { 00643 service_data->flags = 0; 00644 service_data->length_in_bytes += user_data.bytes_used; 00645 if (user_data.more_data == connector_false) 00646 MsgSetLastData(service_data->flags); 00647 } 00648 goto done; 00649 00650 error: 00651 set_data_service_error(service_request, connector_session_error_format); 00652 00653 done: 00654 return status; 00655 } 00656 00657 static connector_status_t process_send_response(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, data_service_context_t * const ds_ptr) 00658 { 00659 connector_status_t status = connector_working; 00660 connector_data_service_send_response_t user_data; 00661 00662 /* Data Service put response format: 00663 * --------------------------------- 00664 * | 0 | 1 | 2... | 00665 * --------------------------------- 00666 * | Opcode | status | Response Data | 00667 * --------------------------------- 00668 */ 00669 enum 00670 { 00671 field_define(put_response, opcode, uint8_t), 00672 field_define(put_response, status, uint8_t), 00673 record_end(put_response) 00674 }; 00675 00676 enum 00677 { 00678 ds_data_success, 00679 ds_data_bad_request, 00680 ds_data_service_unavailable, 00681 ds_data_cloud_error 00682 }; 00683 00684 msg_service_data_t * const service_data = service_request->have_data; 00685 uint8_t * const put_response = service_data->data_ptr; 00686 uint8_t const opcode = message_load_u8(put_response, opcode); 00687 uint8_t const result = message_load_u8(put_response, status); 00688 00689 ASSERT_GOTO(MsgIsStart(service_data->flags), error); 00690 ASSERT_GOTO(opcode == data_service_opcode_put_response, error); 00691 00692 user_data.transport = connector_transport_tcp; 00693 user_data.user_context = ds_ptr->callback_context; 00694 if (service_data->length_in_bytes > record_end(put_response)) 00695 { 00696 int const max_hint_length = (MSG_MAX_RECV_PACKET_SIZE - PACKET_EDP_HEADER_SIZE - record_end(start_packet) - record_end(put_response)); 00697 uint8_t * const hint_start = put_response + record_end(put_response); 00698 uint8_t * const hint_end = put_response + service_data->length_in_bytes; 00699 size_t hint_length = (hint_end - hint_start) < max_hint_length ? hint_end - hint_start : max_hint_length; 00700 char * const hint = (char *)hint_start; 00701 00702 /* Add a null-terminator only if necessary */ 00703 if (hint[hint_length - 1] != '\0') 00704 hint[hint_length] = '\0'; 00705 user_data.hint = hint; 00706 } 00707 else 00708 { 00709 user_data.hint = NULL; 00710 } 00711 00712 switch (result) 00713 { 00714 case ds_data_success: 00715 user_data.response = connector_data_service_send_response_success; 00716 break; 00717 00718 case ds_data_bad_request: 00719 user_data.response = connector_data_service_send_response_bad_request; 00720 break; 00721 00722 case ds_data_service_unavailable: 00723 user_data.response = connector_data_service_send_response_unavailable; 00724 break; 00725 00726 case ds_data_cloud_error: 00727 user_data.response = connector_data_service_send_response_cloud_error; 00728 break; 00729 00730 default: 00731 ASSERT(connector_false); 00732 break; 00733 } 00734 00735 status = call_put_request_user(connector_ptr, service_request, connector_request_id_data_service_send_response, &user_data); 00736 goto done; 00737 00738 error: 00739 set_data_service_error(service_request, connector_session_error_format); 00740 00741 done: 00742 return status; 00743 } 00744 00745 static connector_status_t process_send_error(connector_data_t * const connector_ptr, msg_service_request_t * const service_request, void * const cb_context) 00746 { 00747 connector_status_t status = connector_working; 00748 connector_data_service_status_t user_data; 00749 00750 user_data.transport = connector_transport_tcp; 00751 user_data.user_context = cb_context; 00752 user_data.session_error = connector_session_error_none; 00753 00754 switch (service_request->error_value) 00755 { 00756 case connector_session_error_none: 00757 user_data.status = connector_data_service_status_complete; 00758 break; 00759 00760 case connector_session_error_cancel: 00761 user_data.status = connector_data_service_status_cancel; 00762 break; 00763 00764 case connector_session_error_timeout: 00765 user_data.status = connector_data_service_status_timeout; 00766 break; 00767 00768 default: 00769 user_data.status = connector_data_service_status_session_error; 00770 user_data.session_error = service_request->error_value; 00771 break; 00772 } 00773 00774 status = call_put_request_user(connector_ptr, service_request, connector_request_id_data_service_send_status, &user_data); 00775 00776 return status; 00777 } 00778 00779 static connector_status_t data_service_put_request_callback(connector_data_t * const connector_ptr, msg_service_request_t * const service_request) 00780 { 00781 connector_status_t status; 00782 msg_session_t * const session = service_request->session; 00783 data_service_context_t * const ds_ptr = session->service_context; 00784 00785 switch (service_request->service_type) 00786 { 00787 case msg_service_type_need_data: 00788 status = process_send_request(connector_ptr, service_request, ds_ptr); 00789 break; 00790 00791 case msg_service_type_have_data: 00792 status = process_send_response(connector_ptr, service_request, ds_ptr); 00793 break; 00794 00795 case msg_service_type_error: 00796 { 00797 msg_session_t * const session = service_request->session; 00798 session->error = service_request->error_value; 00799 status = process_send_error(connector_ptr, service_request, ds_ptr->callback_context); 00800 break; 00801 } 00802 00803 case msg_service_type_free: 00804 { 00805 #if (CONNECTOR_VERSION >= 0x02010000) 00806 msg_session_t * const session = service_request->session; 00807 if (session->error == connector_session_error_none) 00808 { 00809 /* If there is no error, call the user to inform that session is done */ 00810 status = process_send_error(connector_ptr, service_request, ds_ptr->callback_context); 00811 if (status != connector_working) 00812 break; 00813 } 00814 #endif 00815 if (ds_ptr != NULL) 00816 status = free_data_buffer(connector_ptr, named_buffer_id(put_request), ds_ptr); 00817 else 00818 status = connector_working; 00819 break; 00820 } 00821 default: 00822 status = connector_idle; 00823 ASSERT(connector_false); 00824 break; 00825 } 00826 00827 return status; 00828 } 00829 00830 static connector_status_t data_service_put_request_init(connector_data_t * const connector_ptr, msg_service_request_t * const service_request) 00831 { 00832 connector_status_t status = connector_working; 00833 connector_session_error_t result = service_request->error_value; 00834 msg_session_t * const session = service_request->session; 00835 connector_request_data_service_send_t * send_ptr = (void *)service_request->have_data; 00836 data_service_context_t * ds_ptr = NULL; 00837 00838 if (send_ptr != NULL) 00839 { 00840 void * ptr; 00841 00842 if ((result != connector_session_error_none) || (session == NULL)) goto error; 00843 00844 status = malloc_data_buffer(connector_ptr, sizeof *ds_ptr, named_buffer_id(put_request), &ptr); 00845 if (status != connector_working) 00846 goto error; 00847 00848 ds_ptr = ptr; 00849 } 00850 else 00851 { 00852 status = connector_invalid_data; 00853 ASSERT_GOTO(connector_false, done); 00854 } 00855 00856 ds_ptr->header = send_ptr; 00857 ds_ptr->callback_context = send_ptr->user_context; 00858 ds_ptr->request_type = connector_request_id_data_service_send_data; 00859 ds_ptr->dp_request = connector_false; 00860 session->service_context = ds_ptr; 00861 00862 #if (defined CONNECTOR_DATA_POINTS) 00863 { 00864 char const data_point_prefix[] = "DataPoint/"; 00865 00866 ds_ptr->dp_request = connector_bool(!strncmp(ds_ptr->header->path, data_point_prefix, strlen(data_point_prefix))); 00867 } 00868 #endif 00869 00870 goto done; 00871 00872 error: 00873 set_data_service_error(service_request, result); 00874 process_send_error(connector_ptr, service_request, send_ptr->user_context); 00875 00876 done: 00877 return status; 00878 } 00879 00880 static connector_status_t data_service_callback(connector_data_t * const connector_ptr, msg_service_request_t * const service_request) 00881 { 00882 connector_status_t status = connector_idle; 00883 msg_session_t * session; 00884 data_service_context_t * ds_ptr; 00885 00886 ASSERT_GOTO(connector_ptr != NULL, done); 00887 ASSERT_GOTO(service_request != NULL, done); 00888 00889 session = service_request->session; 00890 00891 if (service_request->service_type == msg_service_type_pending_request || session == NULL) 00892 { 00893 status = data_service_put_request_init(connector_ptr, service_request); 00894 goto done; 00895 } 00896 00897 ds_ptr = session->service_context; 00898 00899 if (ds_ptr == NULL) 00900 { 00901 status = data_service_device_request_callback(connector_ptr, service_request); 00902 goto done; 00903 } 00904 00905 switch (ds_ptr->request_type) 00906 { 00907 case connector_request_id_data_service_send_length: 00908 case connector_request_id_data_service_send_data: 00909 case connector_request_id_data_service_send_status: 00910 case connector_request_id_data_service_send_response: 00911 status = data_service_put_request_callback(connector_ptr, service_request); 00912 break; 00913 00914 case connector_request_id_data_service_receive_target: 00915 case connector_request_id_data_service_receive_data: 00916 case connector_request_id_data_service_receive_status: 00917 case connector_request_id_data_service_receive_reply_length: 00918 case connector_request_id_data_service_receive_reply_data: 00919 status = data_service_device_request_callback(connector_ptr, service_request); 00920 break; 00921 00922 default: 00923 ASSERT(connector_false); 00924 break; 00925 } 00926 00927 done: 00928 return status; 00929 } 00930 00931 static connector_status_t connector_facility_data_service_cleanup(connector_data_t * const connector_ptr) 00932 { 00933 return msg_cleanup_all_sessions(connector_ptr, msg_service_id_data); 00934 } 00935 00936 static connector_status_t connector_facility_data_service_delete(connector_data_t * const data_ptr) 00937 { 00938 return msg_delete_facility(data_ptr, msg_service_id_data); 00939 } 00940 00941 static connector_status_t connector_facility_data_service_init(connector_data_t * const data_ptr, unsigned int const facility_index) 00942 { 00943 return msg_init_facility(data_ptr, facility_index, msg_service_id_data, data_service_callback); 00944 } 00945 00946 static connector_status_t data_service_initiate(connector_data_t * const connector_ptr, void const * request) 00947 { 00948 connector_status_t status = connector_invalid_data; 00949 00950 ASSERT_GOTO(request != NULL, error); 00951 00952 status = msg_initiate_request(connector_ptr, request) == connector_true ? connector_success : connector_service_busy; 00953 00954 error: 00955 return status; 00956 } 00957 00958 00959
Generated on Tue Jul 12 2022 19:18:38 by
 1.7.2
 1.7.2