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_tcp_send.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 /* The data security coding schemes (a.k.a. encryption types)... */ 00014 #define SECURITY_PROTO_NONE 0x00 /* no encryption, no authentication */ 00015 00016 00017 /* Discovery layer opcodes */ 00018 #define DISC_OP_PAYLOAD 0 00019 #define DISC_OP_DEVICETYPE 4 00020 #define DISC_OP_INITCOMPLETE 5 00021 #define DISC_OP_VENDOR_ID 6 00022 00023 #define tcp_is_send_active(connector_ptr) connector_bool(connector_ptr->edp_data.send_packet.total_length > 0) 00024 00025 static connector_status_t tcp_initiate_send_packet(connector_data_t * const connector_ptr, uint8_t * const edp_header, 00026 size_t const length, uint16_t const type, 00027 send_complete_cb_t send_complete_cb, void * const user_data) 00028 { 00029 connector_status_t status = connector_working; 00030 00031 /* Setup data to be sent. tcp_send_packet_process() will actually 00032 * send out the data. 00033 */ 00034 00035 ASSERT_GOTO(edp_header != NULL, done); 00036 ASSERT_GOTO(length <= UINT16_MAX, done); 00037 00038 if (connector_ptr->edp_data.send_packet.total_length > 0) 00039 { 00040 connector_debug_printf("tcp_initiate_send_packet: unable to trigger another send since previous data is still pending\n"); 00041 status = connector_pending; 00042 goto done; 00043 } 00044 00045 /* 00046 * MTv2 (and later)... 00047 * Packet format for MT version: 00048 * ------------------------ 00049 * | 0 - 1 | 2 - 3 | 4 ... | 00050 * ------------------------ 00051 * | type | length | data | 00052 * ------------------------ 00053 * | EDP Header | 00054 * ---------------- 00055 * 00056 * 00057 */ 00058 00059 /* total bytes to be sent to Device Cloud (packet data length + the edp header length) */ 00060 connector_ptr->edp_data.send_packet.total_length = length + PACKET_EDP_HEADER_SIZE; 00061 connector_ptr->edp_data.send_packet.ptr = edp_header; 00062 00063 message_store_be16(edp_header, type, type); 00064 00065 { 00066 uint16_t const length16 = (uint16_t) length; 00067 00068 ASSERT(length <= UINT16_MAX); 00069 message_store_be16(edp_header, length, length16); 00070 } 00071 00072 /* clear the actual number of bytes to be sent */ 00073 connector_ptr->edp_data.send_packet.bytes_sent = 0; 00074 connector_ptr->edp_data.send_packet.complete_cb = send_complete_cb; 00075 connector_ptr->edp_data.send_packet.user_data = user_data; 00076 done: 00077 return status; 00078 } 00079 00080 static connector_status_t tcp_initiate_send_facility_packet(connector_data_t * const connector_ptr, uint8_t * const edp_header, 00081 size_t const length, uint16_t const facility, 00082 send_complete_cb_t send_complete_cb, void * const user_data) 00083 { 00084 uint8_t * const edp_protocol = edp_header + PACKET_EDP_HEADER_SIZE; 00085 00086 00087 /* this function is to set up a facility packet to be sent. 00088 * Setup security coding, discovery payload & facility. 00089 * 00090 * facility packet: 00091 * ------------------------------------------------------------------------------------- 00092 * | 0 - 1 | 2 - 3 | 4 | 5 | 6 - 7 | 8... | 00093 * ------------------------------------------------------------------------------------- 00094 * | type | length | data security coding | discovery payload | facility | facility data| 00095 * ------------------------------------------------------------------------------------- 00096 * | EDP Header | EDP Protocol | 00097 * ---------------------------------------------------------------------- 00098 */ 00099 message_store_u8(edp_protocol, sec_coding, SECURITY_PROTO_NONE); 00100 message_store_u8(edp_protocol, payload, DISC_OP_PAYLOAD); 00101 message_store_be16(edp_protocol, facility, facility); 00102 00103 00104 return tcp_initiate_send_packet(connector_ptr, edp_header, 00105 (length + PACKET_EDP_PROTOCOL_SIZE), 00106 E_MSG_MT2_TYPE_PAYLOAD, 00107 send_complete_cb, 00108 user_data); 00109 } 00110 00111 static connector_callback_status_t tcp_send_buffer(connector_data_t * const connector_ptr, uint8_t * const buffer, size_t * const length) 00112 { 00113 connector_callback_status_t status; 00114 connector_network_send_t send_data; 00115 connector_request_id_t request_id; 00116 00117 send_data.buffer = buffer; 00118 send_data.bytes_available = *length; 00119 send_data.bytes_used = 0; 00120 send_data.handle = connector_ptr->edp_data.network_handle; 00121 00122 request_id.network_request = connector_request_id_network_send; 00123 status = connector_callback(connector_ptr->callback, connector_class_id_network_tcp, request_id, &send_data); 00124 ASSERT(status != connector_callback_unrecognized); 00125 switch (status) 00126 { 00127 case connector_callback_continue: 00128 *length = send_data.bytes_used; 00129 if (*length > 0) 00130 { 00131 /* Retain the "last (RX) message send" time. */ 00132 if (get_system_time(connector_ptr, &connector_ptr->edp_data.keepalive.last_rx_sent_time) != connector_working) 00133 { 00134 status = connector_callback_abort; 00135 } 00136 } 00137 break; 00138 case connector_callback_busy: 00139 *length = 0; 00140 break; 00141 case connector_callback_unrecognized: 00142 status = connector_callback_abort; 00143 /* no break */ 00144 case connector_callback_abort: 00145 break; 00146 case connector_callback_error: 00147 edp_set_close_status(connector_ptr, connector_close_status_device_error); 00148 break; 00149 } 00150 00151 return status; 00152 } 00153 00154 static connector_status_t tcp_release_packet_buffer(connector_data_t * const connector_ptr, uint8_t const * const packet, connector_status_t const status, void * const user_data) 00155 { 00156 /* this is called when the Connector is done sending or after tcp_get_packet_buffer() 00157 * is called to release connector_ptr->edp_data.send_packet.packet_buffer.buffer. 00158 * 00159 */ 00160 UNUSED_PARAMETER(status); 00161 UNUSED_PARAMETER(packet); 00162 UNUSED_PARAMETER(user_data); 00163 00164 ASSERT(connector_ptr->edp_data.send_packet.packet_buffer.buffer == packet); 00165 00166 connector_ptr->edp_data.send_packet.packet_buffer.in_use = connector_false; 00167 00168 return connector_working; 00169 } 00170 #if (defined CONNECTOR_DEBUG) 00171 static unsigned int debug_count = 0; 00172 #endif 00173 00174 static uint8_t * tcp_get_packet_buffer(connector_data_t * const connector_ptr, uint16_t const facility, uint8_t ** data_ptr, size_t * data_length) 00175 { 00176 #define MIN_EDP_MESSAGE_SIZE (PACKET_EDP_HEADER_SIZE +CLOUD_URL_LENGTH) 00177 uint8_t * packet = NULL; 00178 uint8_t * ptr = NULL; 00179 size_t length = 0; 00180 00181 /* Return a pointer to caller to setup data to be sent to Device Cloud. 00182 * Must call tcp_release_packet_buffer() to release the buffer (pass 00183 * tcp_release_packet_buffer as complete_callback to tcp_initiate_send_packet() 00184 * or tcp_initiate_send_facility_packet(). 00185 */ 00186 00187 00188 /* make sure no send is pending */ 00189 if ((connector_ptr->edp_data.send_packet.total_length == 0) && 00190 (!connector_ptr->edp_data.send_packet.packet_buffer.in_use)) 00191 { 00192 connector_ptr->edp_data.send_packet.packet_buffer.in_use = connector_true; 00193 00194 packet = connector_ptr->edp_data.send_packet.packet_buffer.buffer; 00195 00196 /* set ptr to the data portion */ 00197 ptr = GET_PACKET_DATA_POINTER(packet, PACKET_EDP_HEADER_SIZE); 00198 00199 if (facility != E_MSG_MT2_MSG_NUM) 00200 { 00201 /* set ptr to the data portion of facility packet */ 00202 ptr += PACKET_EDP_PROTOCOL_SIZE; 00203 } 00204 00205 { 00206 size_t const max_packet_size = sizeof connector_ptr->edp_data.send_packet.packet_buffer.buffer; 00207 size_t const header_size = (size_t)(ptr - packet); 00208 00209 ASSERT(max_packet_size >= MIN_EDP_MESSAGE_SIZE); 00210 ASSERT(ptr > packet); 00211 length = max_packet_size - header_size; 00212 } 00213 #if (defined CONNECTOR_DEBUG) 00214 debug_count = 0; 00215 #endif 00216 00217 } 00218 #if (defined CONNECTOR_DEBUG) 00219 else 00220 { 00221 if (debug_count == 0) 00222 connector_debug_printf("tcp_get packet buffer: send pending\n"); 00223 00224 debug_count++; 00225 } 00226 #endif 00227 if (data_ptr != NULL) 00228 { 00229 *data_ptr = ptr; 00230 } 00231 00232 if (data_length != NULL) 00233 { 00234 *data_length = length; 00235 } 00236 00237 return packet; 00238 } 00239 00240 static connector_status_t tcp_rx_keepalive_process(connector_data_t * const connector_ptr) 00241 { 00242 connector_status_t status = connector_idle; 00243 00244 if (edp_get_active_state(connector_ptr) == connector_transport_open) 00245 { 00246 goto done; 00247 } 00248 00249 /* Sends rx keepalive if keepalive timing is expired. 00250 * 00251 * last_rx_keepalive_time is last time we sent Rx keepalive. 00252 */ 00253 if (is_valid_timing_limit(connector_ptr, connector_ptr->edp_data.keepalive.last_rx_sent_time, GET_RX_KEEPALIVE_INTERVAL(connector_ptr))) 00254 { 00255 /* not expired yet. no need to send rx keepalive */ 00256 goto done; 00257 } 00258 00259 connector_debug_printf("tcp_rx_keepalive_process: time to send Rx keepalive\n"); 00260 00261 status = tcp_initiate_send_packet(connector_ptr, connector_ptr->edp_data.keepalive.send_rx_packet, 0, E_MSG_MT2_TYPE_KA_KEEPALIVE, NULL, NULL); 00262 00263 done: 00264 return status; 00265 } 00266 00267 static connector_status_t tcp_send_complete_callback(connector_data_t * const connector_ptr, connector_status_t status) 00268 { 00269 connector_status_t result = connector_working; 00270 send_complete_cb_t callback = connector_ptr->edp_data.send_packet.complete_cb; 00271 00272 if (callback != NULL) 00273 { 00274 connector_ptr->edp_data.send_packet.complete_cb = NULL; 00275 result = callback(connector_ptr, connector_ptr->edp_data.send_packet.ptr, status, connector_ptr->edp_data.send_packet.user_data); 00276 ASSERT(result != connector_pending); 00277 } 00278 00279 return result; 00280 } 00281 00282 static connector_status_t edp_tcp_send_process(connector_data_t * const connector_ptr) 00283 { 00284 connector_status_t result = connector_idle; 00285 00286 /* if nothing needs to be sent, check whether we need to send rx keepalive */ 00287 if (connector_ptr->edp_data.send_packet.total_length == 0) 00288 { 00289 00290 result = tcp_rx_keepalive_process(connector_ptr); 00291 } 00292 00293 if (connector_ptr->edp_data.send_packet.total_length > 0) 00294 { 00295 /* We have something to be sent */ 00296 00297 uint8_t * const buf = connector_ptr->edp_data.send_packet.ptr + connector_ptr->edp_data.send_packet.bytes_sent; 00298 size_t length = connector_ptr->edp_data.send_packet.total_length; 00299 00300 connector_callback_status_t const status = tcp_send_buffer(connector_ptr, buf, &length); 00301 00302 switch (status) 00303 { 00304 case connector_callback_continue: 00305 connector_ptr->edp_data.send_packet.total_length -= length; 00306 connector_ptr->edp_data.send_packet.bytes_sent += length; 00307 00308 if (connector_ptr->edp_data.send_packet.total_length == 0) 00309 { /* sent completed so let's call the complete callback */ 00310 result = tcp_send_complete_callback(connector_ptr, connector_success); 00311 } 00312 else if (connector_ptr->edp_data.send_packet.total_length > 0) 00313 { 00314 result = connector_pending; 00315 } 00316 break; 00317 00318 case connector_callback_busy: 00319 result = connector_pending; 00320 goto done; 00321 00322 case connector_callback_error: 00323 edp_set_close_status(connector_ptr, connector_close_status_device_error); 00324 edp_set_active_state(connector_ptr, connector_transport_close); 00325 break; 00326 case connector_callback_abort: 00327 edp_set_close_status(connector_ptr, connector_close_status_abort); 00328 edp_set_active_state(connector_ptr, connector_transport_close); 00329 break; 00330 default: 00331 ASSERT(connector_false); 00332 break; 00333 } 00334 } 00335 00336 done: 00337 return result; 00338 00339 } 00340 00341 00342
Generated on Tue Jul 12 2022 19:18:38 by
1.7.2