Etherios Cloud Connector very first porting for mbed. Tested in an LPC1768

Etherios Cloud Connector for Embedded v2.1.0.3 library for mbed. Early porting.

This port is centered mainly in the platform code. So it should work properly with the provided examples of send_data, device_request, data_points, RCI and firmware_update (stub implementation, not a real one... yet ;-)). Filesystem is not implemented yet, and some examples might need changes.

To run, it needs the following libraries: - mbed - mbed-rtos - EthernetInterface

Find more information (and the source code!) about Etherios Cloud Connector for Embedded here: http://www.etherios.com/products/devicecloud/support/connector and in: http://www.etherios.com

Committer:
spastor
Date:
Tue Dec 03 13:34:02 2013 +0000
Revision:
0:1c358ea10753
First commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
spastor 0:1c358ea10753 1 /*
spastor 0:1c358ea10753 2 * Copyright (c) 2013 Digi International Inc.,
spastor 0:1c358ea10753 3 * All rights not expressly granted are reserved.
spastor 0:1c358ea10753 4 *
spastor 0:1c358ea10753 5 * This Source Code Form is subject to the terms of the Mozilla Public
spastor 0:1c358ea10753 6 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
spastor 0:1c358ea10753 7 * You can obtain one at http://mozilla.org/MPL/2.0/.
spastor 0:1c358ea10753 8 *
spastor 0:1c358ea10753 9 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
spastor 0:1c358ea10753 10 * =======================================================================
spastor 0:1c358ea10753 11 */
spastor 0:1c358ea10753 12
spastor 0:1c358ea10753 13 static connector_buffer_t * tcp_new_receive_packet(connector_data_t * const connector_ptr)
spastor 0:1c358ea10753 14 {
spastor 0:1c358ea10753 15 connector_buffer_t * buffer_ptr;
spastor 0:1c358ea10753 16 connector_buffer_t * packet = NULL;
spastor 0:1c358ea10753 17
spastor 0:1c358ea10753 18 /* return an available packet for receiving data */
spastor 0:1c358ea10753 19 buffer_ptr = connector_ptr->edp_data.receive_packet.free_packet_buffer;
spastor 0:1c358ea10753 20 if (buffer_ptr != NULL)
spastor 0:1c358ea10753 21 {
spastor 0:1c358ea10753 22 packet = buffer_ptr;
spastor 0:1c358ea10753 23 connector_ptr->edp_data.receive_packet.free_packet_buffer = buffer_ptr->next;
spastor 0:1c358ea10753 24 }
spastor 0:1c358ea10753 25
spastor 0:1c358ea10753 26
spastor 0:1c358ea10753 27 return packet;
spastor 0:1c358ea10753 28 }
spastor 0:1c358ea10753 29
spastor 0:1c358ea10753 30 static void tcp_release_receive_packet(connector_data_t * const connector_ptr, connector_buffer_t const * const packet)
spastor 0:1c358ea10753 31 {
spastor 0:1c358ea10753 32 ASSERT(packet != NULL);
spastor 0:1c358ea10753 33
spastor 0:1c358ea10753 34 /* release a packet that is from tcp_new_receive_packet() */
spastor 0:1c358ea10753 35 if (packet != NULL)
spastor 0:1c358ea10753 36 {
spastor 0:1c358ea10753 37 connector_buffer_t * const buffer_ptr = (connector_buffer_t *)packet;
spastor 0:1c358ea10753 38
spastor 0:1c358ea10753 39 buffer_ptr->next = connector_ptr->edp_data.receive_packet.free_packet_buffer;
spastor 0:1c358ea10753 40 connector_ptr->edp_data.receive_packet.free_packet_buffer = buffer_ptr;
spastor 0:1c358ea10753 41 }
spastor 0:1c358ea10753 42 return;
spastor 0:1c358ea10753 43 }
spastor 0:1c358ea10753 44
spastor 0:1c358ea10753 45
spastor 0:1c358ea10753 46 static connector_callback_status_t tcp_receive_buffer(connector_data_t * const connector_ptr, uint8_t * const buffer, size_t * const length)
spastor 0:1c358ea10753 47 {
spastor 0:1c358ea10753 48 connector_callback_status_t status;
spastor 0:1c358ea10753 49 connector_request_id_t request_id;
spastor 0:1c358ea10753 50
spastor 0:1c358ea10753 51 /* Call callback to receive data from Device Cloud */
spastor 0:1c358ea10753 52 request_id.network_request = connector_request_id_network_receive;
spastor 0:1c358ea10753 53
spastor 0:1c358ea10753 54 {
spastor 0:1c358ea10753 55 connector_network_receive_t read_data;
spastor 0:1c358ea10753 56
spastor 0:1c358ea10753 57 read_data.handle = connector_ptr->edp_data.network_handle;
spastor 0:1c358ea10753 58 read_data.buffer = buffer;
spastor 0:1c358ea10753 59 read_data.bytes_available = *length;
spastor 0:1c358ea10753 60 read_data.bytes_used = 0;
spastor 0:1c358ea10753 61
spastor 0:1c358ea10753 62
spastor 0:1c358ea10753 63 status = connector_callback(connector_ptr->callback, connector_class_id_network_tcp, request_id, &read_data);
spastor 0:1c358ea10753 64 ASSERT(status != connector_callback_unrecognized);
spastor 0:1c358ea10753 65 switch (status)
spastor 0:1c358ea10753 66 {
spastor 0:1c358ea10753 67 case connector_callback_unrecognized:
spastor 0:1c358ea10753 68 status = connector_callback_abort;
spastor 0:1c358ea10753 69 /* no break */
spastor 0:1c358ea10753 70 case connector_callback_abort:
spastor 0:1c358ea10753 71 connector_debug_printf("tcp_receive_buffer: callback returns abort\n");
spastor 0:1c358ea10753 72 goto done;
spastor 0:1c358ea10753 73 case connector_callback_busy:
spastor 0:1c358ea10753 74 *length = 0;
spastor 0:1c358ea10753 75 break;
spastor 0:1c358ea10753 76 case connector_callback_continue:
spastor 0:1c358ea10753 77 *length = read_data.bytes_used;
spastor 0:1c358ea10753 78 break;
spastor 0:1c358ea10753 79 case connector_callback_error:
spastor 0:1c358ea10753 80 edp_set_close_status(connector_ptr, connector_close_status_device_error);
spastor 0:1c358ea10753 81 goto done;
spastor 0:1c358ea10753 82 }
spastor 0:1c358ea10753 83
spastor 0:1c358ea10753 84 if (read_data.bytes_used > 0 || connector_ptr->edp_data.keepalive.last_tx_received_time == 0)
spastor 0:1c358ea10753 85 {
spastor 0:1c358ea10753 86 /* Retain the "last (tx keepalive) message send" time. */
spastor 0:1c358ea10753 87 if (get_system_time(connector_ptr, &connector_ptr->edp_data.keepalive.last_tx_received_time) != connector_working)
spastor 0:1c358ea10753 88 {
spastor 0:1c358ea10753 89 status = connector_callback_abort;
spastor 0:1c358ea10753 90 }
spastor 0:1c358ea10753 91 else
spastor 0:1c358ea10753 92 {
spastor 0:1c358ea10753 93 if (connector_ptr->edp_data.keepalive.miss_tx_count > 0)
spastor 0:1c358ea10753 94 {
spastor 0:1c358ea10753 95 if (notify_status(connector_ptr->callback, connector_tcp_keepalive_restored) != connector_working)
spastor 0:1c358ea10753 96 status = connector_callback_abort;
spastor 0:1c358ea10753 97 connector_ptr->edp_data.keepalive.miss_tx_count = 0;
spastor 0:1c358ea10753 98 }
spastor 0:1c358ea10753 99 }
spastor 0:1c358ea10753 100 goto done;
spastor 0:1c358ea10753 101 }
spastor 0:1c358ea10753 102 }
spastor 0:1c358ea10753 103
spastor 0:1c358ea10753 104
spastor 0:1c358ea10753 105 /* check Tx keepalive timing */
spastor 0:1c358ea10753 106 if (GET_TX_KEEPALIVE_INTERVAL(connector_ptr) > 0)
spastor 0:1c358ea10753 107 {
spastor 0:1c358ea10753 108 unsigned long const tx_keepalive_interval = GET_TX_KEEPALIVE_INTERVAL(connector_ptr);
spastor 0:1c358ea10753 109
spastor 0:1c358ea10753 110 unsigned long const wait_count = connector_ptr->edp_data.keepalive.miss_tx_count + UINT32_C(1);
spastor 0:1c358ea10753 111 unsigned long const max_timeout = (tx_keepalive_interval * wait_count);
spastor 0:1c358ea10753 112
spastor 0:1c358ea10753 113 if (!is_valid_timing_limit(connector_ptr, connector_ptr->edp_data.keepalive.last_tx_received_time, max_timeout))
spastor 0:1c358ea10753 114 {
spastor 0:1c358ea10753 115 /* notify callback we have missing a tx keep alive */
spastor 0:1c358ea10753 116 if (notify_status(connector_ptr->callback, connector_tcp_keepalive_missed) != connector_working)
spastor 0:1c358ea10753 117 {
spastor 0:1c358ea10753 118 status = connector_callback_abort;
spastor 0:1c358ea10753 119 goto done;
spastor 0:1c358ea10753 120 }
spastor 0:1c358ea10753 121 connector_ptr->edp_data.keepalive.miss_tx_count++;
spastor 0:1c358ea10753 122 if (connector_ptr->edp_data.keepalive.miss_tx_count == GET_WAIT_COUNT(connector_ptr))
spastor 0:1c358ea10753 123 {
spastor 0:1c358ea10753 124 /* consider a lost connection */
spastor 0:1c358ea10753 125 if (notify_error_status(connector_ptr->callback, connector_class_id_network_tcp, request_id, connector_keepalive_error) != connector_working)
spastor 0:1c358ea10753 126 {
spastor 0:1c358ea10753 127 status = connector_callback_abort;
spastor 0:1c358ea10753 128 goto done;
spastor 0:1c358ea10753 129 }
spastor 0:1c358ea10753 130
spastor 0:1c358ea10753 131 connector_debug_printf("connector_receive: keepalive fails\n");
spastor 0:1c358ea10753 132 edp_set_close_status(connector_ptr, connector_close_status_no_keepalive);
spastor 0:1c358ea10753 133 status = connector_callback_error;
spastor 0:1c358ea10753 134 }
spastor 0:1c358ea10753 135 }
spastor 0:1c358ea10753 136
spastor 0:1c358ea10753 137 }
spastor 0:1c358ea10753 138
spastor 0:1c358ea10753 139
spastor 0:1c358ea10753 140 done:
spastor 0:1c358ea10753 141 connector_ptr->edp_data.receive_packet.timeout = MAX_RECEIVE_TIMEOUT_IN_SECONDS;
spastor 0:1c358ea10753 142 return status;
spastor 0:1c358ea10753 143 }
spastor 0:1c358ea10753 144
spastor 0:1c358ea10753 145
spastor 0:1c358ea10753 146 static connector_callback_status_t tcp_receive_data_status(connector_data_t * const connector_ptr)
spastor 0:1c358ea10753 147 {
spastor 0:1c358ea10753 148 connector_callback_status_t status = connector_callback_continue;
spastor 0:1c358ea10753 149
spastor 0:1c358ea10753 150 /* send data if we have more data to send */
spastor 0:1c358ea10753 151 if (connector_ptr->edp_data.receive_packet.bytes_received < connector_ptr->edp_data.receive_packet.total_length)
spastor 0:1c358ea10753 152 {
spastor 0:1c358ea10753 153 uint8_t * const buf = connector_ptr->edp_data.receive_packet.ptr + connector_ptr->edp_data.receive_packet.bytes_received;
spastor 0:1c358ea10753 154 size_t length = connector_ptr->edp_data.receive_packet.total_length - connector_ptr->edp_data.receive_packet.bytes_received;
spastor 0:1c358ea10753 155 status = tcp_receive_buffer(connector_ptr, buf, &length);
spastor 0:1c358ea10753 156
spastor 0:1c358ea10753 157 if (status == connector_callback_continue)
spastor 0:1c358ea10753 158 {
spastor 0:1c358ea10753 159 connector_ptr->edp_data.receive_packet.bytes_received += length;
spastor 0:1c358ea10753 160 }
spastor 0:1c358ea10753 161 else if (status != connector_callback_busy)
spastor 0:1c358ea10753 162 {
spastor 0:1c358ea10753 163 goto done;
spastor 0:1c358ea10753 164 }
spastor 0:1c358ea10753 165 }
spastor 0:1c358ea10753 166
spastor 0:1c358ea10753 167 if (connector_ptr->edp_data.receive_packet.bytes_received < connector_ptr->edp_data.receive_packet.total_length)
spastor 0:1c358ea10753 168 {
spastor 0:1c358ea10753 169 /* still more data */
spastor 0:1c358ea10753 170 status = connector_callback_busy;
spastor 0:1c358ea10753 171 }
spastor 0:1c358ea10753 172 done:
spastor 0:1c358ea10753 173 return status;
spastor 0:1c358ea10753 174 }
spastor 0:1c358ea10753 175
spastor 0:1c358ea10753 176
spastor 0:1c358ea10753 177 static connector_status_t tcp_receive_packet(connector_data_t * const connector_ptr, connector_buffer_t ** packet)
spastor 0:1c358ea10753 178 {
spastor 0:1c358ea10753 179 enum {
spastor 0:1c358ea10753 180 receive_packet_init,
spastor 0:1c358ea10753 181 receive_packet_type,
spastor 0:1c358ea10753 182 receive_packet_length,
spastor 0:1c358ea10753 183 receive_packet_data,
spastor 0:1c358ea10753 184 receive_packet_complete
spastor 0:1c358ea10753 185 };
spastor 0:1c358ea10753 186
spastor 0:1c358ea10753 187 connector_status_t result = connector_idle;
spastor 0:1c358ea10753 188
spastor 0:1c358ea10753 189 *packet = NULL;
spastor 0:1c358ea10753 190
spastor 0:1c358ea10753 191 ASSERT_GOTO(edp_get_edp_state(connector_ptr) != edp_communication_connect_to_cloud, done);
spastor 0:1c358ea10753 192
spastor 0:1c358ea10753 193 /*
spastor 0:1c358ea10753 194 * Read the MT message type.
spastor 0:1c358ea10753 195 *
spastor 0:1c358ea10753 196 * For MT version 2, there are numerous message types. Some of these
spastor 0:1c358ea10753 197 * messages require special handling, in that they may be legacy EDP
spastor 0:1c358ea10753 198 * version response message varieties. These messages are sent by
spastor 0:1c358ea10753 199 * device cloud that does not support MTv2. Since the client doesn't support
spastor 0:1c358ea10753 200 * both MTv1 and MTv2 concurrently, an MTv2 client must terminate its
spastor 0:1c358ea10753 201 * MT connection if it finds the Device Cloud to be incompatible insofar as
spastor 0:1c358ea10753 202 * the MT version is concerned.
spastor 0:1c358ea10753 203 *
spastor 0:1c358ea10753 204 * We only accept messages of the expected types from the Device Cloud. Any
spastor 0:1c358ea10753 205 * message other than an expected type is handled as an error, and an
spastor 0:1c358ea10753 206 * error is returned to the caller. This must be done since any unknown
spastor 0:1c358ea10753 207 * message type cannot be correctly parsed for length and discarded from
spastor 0:1c358ea10753 208 * the input stream.
spastor 0:1c358ea10753 209 */
spastor 0:1c358ea10753 210
spastor 0:1c358ea10753 211 /* we have to read 3 times to get a complete packet.
spastor 0:1c358ea10753 212 * 1. read message type
spastor 0:1c358ea10753 213 * 2. read message length
spastor 0:1c358ea10753 214 * 3. read actual message data
spastor 0:1c358ea10753 215 *
spastor 0:1c358ea10753 216 * So we use index == receive_packet_init to initialize the packet before starting reading.
spastor 0:1c358ea10753 217 * When index == receive_packet_type, set to receive message type. After message type is received,
spastor 0:1c358ea10753 218 * we must check valid message type.
spastor 0:1c358ea10753 219 *
spastor 0:1c358ea10753 220 * When index == receive_packet_length, set to receive message length.
spastor 0:1c358ea10753 221 * When index == receive_packet_data, set to receive message data.
spastor 0:1c358ea10753 222 * When index == receive_packet_complete, message data is completely received and
spastor 0:1c358ea10753 223 * reset index = receive_packet_init and exit.
spastor 0:1c358ea10753 224 *
spastor 0:1c358ea10753 225 */
spastor 0:1c358ea10753 226 while (connector_ptr->edp_data.receive_packet.index <= receive_packet_complete)
spastor 0:1c358ea10753 227 {
spastor 0:1c358ea10753 228 connector_callback_status_t status = connector_callback_continue;
spastor 0:1c358ea10753 229
spastor 0:1c358ea10753 230 if (connector_ptr->edp_data.receive_packet.index != receive_packet_init)
spastor 0:1c358ea10753 231 { /* continue for any pending receive */
spastor 0:1c358ea10753 232 status = tcp_receive_data_status(connector_ptr);
spastor 0:1c358ea10753 233
spastor 0:1c358ea10753 234 switch (status)
spastor 0:1c358ea10753 235 {
spastor 0:1c358ea10753 236 case connector_callback_continue:
spastor 0:1c358ea10753 237 break;
spastor 0:1c358ea10753 238 case connector_callback_busy:
spastor 0:1c358ea10753 239 result = (connector_ptr->edp_data.receive_packet.index <= receive_packet_length) ? connector_idle : connector_pending;
spastor 0:1c358ea10753 240 goto done;
spastor 0:1c358ea10753 241 case connector_callback_error:
spastor 0:1c358ea10753 242 result = connector_unavailable;
spastor 0:1c358ea10753 243 goto done;
spastor 0:1c358ea10753 244 case connector_callback_abort:
spastor 0:1c358ea10753 245 edp_set_close_status(connector_ptr, connector_close_status_abort);
spastor 0:1c358ea10753 246 result = connector_abort;
spastor 0:1c358ea10753 247 goto done;
spastor 0:1c358ea10753 248 default:
spastor 0:1c358ea10753 249 ASSERT(connector_false);
spastor 0:1c358ea10753 250 }
spastor 0:1c358ea10753 251 }
spastor 0:1c358ea10753 252 result = connector_pending;
spastor 0:1c358ea10753 253
spastor 0:1c358ea10753 254 switch (connector_ptr->edp_data.receive_packet.index)
spastor 0:1c358ea10753 255 {
spastor 0:1c358ea10753 256 case receive_packet_init:
spastor 0:1c358ea10753 257 /* initialize and setup packet for receive */
spastor 0:1c358ea10753 258 connector_ptr->edp_data.receive_packet.packet_type = 0;
spastor 0:1c358ea10753 259 connector_ptr->edp_data.receive_packet.packet_length = 0;
spastor 0:1c358ea10753 260 connector_ptr->edp_data.receive_packet.bytes_received = 0;
spastor 0:1c358ea10753 261 connector_ptr->edp_data.receive_packet.total_length = 0;
spastor 0:1c358ea10753 262 connector_ptr->edp_data.receive_packet.index = 0;
spastor 0:1c358ea10753 263
spastor 0:1c358ea10753 264 if (edp_get_active_state(connector_ptr) == connector_transport_open)
spastor 0:1c358ea10753 265 {
spastor 0:1c358ea10753 266 /* We are still in edp connection process.
spastor 0:1c358ea10753 267 * So we need to setup the packet for any message
spastor 0:1c358ea10753 268 * during edp connection process since no facility is
spastor 0:1c358ea10753 269 * running.
spastor 0:1c358ea10753 270 * Otherwise, we setup the packet in receive_packet_data index
spastor 0:1c358ea10753 271 * to receive actual data. Otherwise, we don't have actual
spastor 0:1c358ea10753 272 * data received but we need to be able to receive keepalive.
spastor 0:1c358ea10753 273 */
spastor 0:1c358ea10753 274 connector_ptr->edp_data.receive_packet.data_packet = tcp_new_receive_packet(connector_ptr);
spastor 0:1c358ea10753 275 if (connector_ptr->edp_data.receive_packet.data_packet == NULL)
spastor 0:1c358ea10753 276 {
spastor 0:1c358ea10753 277 result = connector_idle;
spastor 0:1c358ea10753 278 goto done;
spastor 0:1c358ea10753 279 }
spastor 0:1c358ea10753 280 }
spastor 0:1c358ea10753 281
spastor 0:1c358ea10753 282 connector_ptr->edp_data.receive_packet.index++;
spastor 0:1c358ea10753 283 break;
spastor 0:1c358ea10753 284
spastor 0:1c358ea10753 285 case receive_packet_type:
spastor 0:1c358ea10753 286 /* set to read the message type */
spastor 0:1c358ea10753 287 connector_ptr->edp_data.receive_packet.ptr = (uint8_t *)&connector_ptr->edp_data.receive_packet.packet_type;
spastor 0:1c358ea10753 288 connector_ptr->edp_data.receive_packet.bytes_received = 0;
spastor 0:1c358ea10753 289 connector_ptr->edp_data.receive_packet.total_length = sizeof connector_ptr->edp_data.receive_packet.packet_type;
spastor 0:1c358ea10753 290 connector_ptr->edp_data.receive_packet.index++;
spastor 0:1c358ea10753 291 break;
spastor 0:1c358ea10753 292
spastor 0:1c358ea10753 293 case receive_packet_length:
spastor 0:1c358ea10753 294 {
spastor 0:1c358ea10753 295 /* Got message type let's get to message length.
spastor 0:1c358ea10753 296 * So make sure we support the message type.
spastor 0:1c358ea10753 297 * Then, set to read message length.
spastor 0:1c358ea10753 298 */
spastor 0:1c358ea10753 299 uint16_t type_val;
spastor 0:1c358ea10753 300
spastor 0:1c358ea10753 301 type_val = FROM_BE16(connector_ptr->edp_data.receive_packet.packet_type);
spastor 0:1c358ea10753 302 connector_ptr->edp_data.receive_packet.packet_type = type_val;
spastor 0:1c358ea10753 303
spastor 0:1c358ea10753 304 switch (type_val)
spastor 0:1c358ea10753 305 {
spastor 0:1c358ea10753 306 /* Expected MTv2 message types... */
spastor 0:1c358ea10753 307 case E_MSG_MT2_TYPE_VERSION_OK:
spastor 0:1c358ea10753 308 break;
spastor 0:1c358ea10753 309 case E_MSG_MT2_TYPE_KA_KEEPALIVE:
spastor 0:1c358ea10753 310 break;
spastor 0:1c358ea10753 311 case E_MSG_MT2_TYPE_PAYLOAD:
spastor 0:1c358ea10753 312 break;
spastor 0:1c358ea10753 313 case E_MSG_MT2_TYPE_LEGACY_EDP_VER_RESP:
spastor 0:1c358ea10753 314 case E_MSG_MT2_TYPE_VERSION_BAD:
spastor 0:1c358ea10753 315 case E_MSG_MT2_TYPE_CLOUD_OVERLOAD:
spastor 0:1c358ea10753 316 connector_debug_printf("tcp_receive_packet: unsupported or unexpected error type 0x%x\n", (unsigned) type_val);
spastor 0:1c358ea10753 317 edp_set_close_status(connector_ptr, connector_close_status_abort);
spastor 0:1c358ea10753 318 result = connector_abort;
spastor 0:1c358ea10753 319 goto done;
spastor 0:1c358ea10753 320 /* Unexpected/unknown MTv2 message types... */
spastor 0:1c358ea10753 321 case E_MSG_MT2_TYPE_VERSION:
spastor 0:1c358ea10753 322 case E_MSG_MT2_TYPE_KA_RX_INTERVAL:
spastor 0:1c358ea10753 323 case E_MSG_MT2_TYPE_KA_TX_INTERVAL:
spastor 0:1c358ea10753 324 case E_MSG_MT2_TYPE_KA_WAIT:
spastor 0:1c358ea10753 325 default:
spastor 0:1c358ea10753 326 /* Just tell caller we have unexpected packet message */
spastor 0:1c358ea10753 327 connector_debug_printf("tcp_receive_packet: unsupported or unexpected error type 0x%x\n", (unsigned) type_val);
spastor 0:1c358ea10753 328 break;
spastor 0:1c358ea10753 329 }
spastor 0:1c358ea10753 330
spastor 0:1c358ea10753 331 /* set up to read message length */
spastor 0:1c358ea10753 332 connector_ptr->edp_data.receive_packet.ptr = (uint8_t *)&connector_ptr->edp_data.receive_packet.packet_length;
spastor 0:1c358ea10753 333 connector_ptr->edp_data.receive_packet.bytes_received = 0;
spastor 0:1c358ea10753 334 connector_ptr->edp_data.receive_packet.total_length = sizeof connector_ptr->edp_data.receive_packet.packet_length;
spastor 0:1c358ea10753 335 connector_ptr->edp_data.receive_packet.index++;
spastor 0:1c358ea10753 336 break;
spastor 0:1c358ea10753 337 }
spastor 0:1c358ea10753 338 case receive_packet_data:
spastor 0:1c358ea10753 339 {
spastor 0:1c358ea10753 340 /* got packet length so set to read message data */
spastor 0:1c358ea10753 341 uint16_t packet_length = FROM_BE16(connector_ptr->edp_data.receive_packet.packet_length);
spastor 0:1c358ea10753 342
spastor 0:1c358ea10753 343 if (connector_ptr->edp_data.receive_packet.packet_type != E_MSG_MT2_TYPE_PAYLOAD)
spastor 0:1c358ea10753 344 {
spastor 0:1c358ea10753 345 /*
spastor 0:1c358ea10753 346 * For all but payload messages, the length field value should be
spastor 0:1c358ea10753 347 * zero, as there is no data accompanying the message. The MT
spastor 0:1c358ea10753 348 * messages to which this applies here are:
spastor 0:1c358ea10753 349 * E_MSG_MT2_TYPE_VERSION_OK
spastor 0:1c358ea10753 350 * E_MSG_MT2_TYPE_VERSION_BAD
spastor 0:1c358ea10753 351 * E_MSG_MT2_TYPE_CLOUD_OVERLOAD
spastor 0:1c358ea10753 352 * E_MSG_MT2_TYPE_KA_KEEPALIVE
spastor 0:1c358ea10753 353 */
spastor 0:1c358ea10753 354 if (packet_length != 0)
spastor 0:1c358ea10753 355 {
spastor 0:1c358ea10753 356 connector_debug_printf("connector_get_receive_packet: Invalid payload\n");
spastor 0:1c358ea10753 357 }
spastor 0:1c358ea10753 358 }
spastor 0:1c358ea10753 359
spastor 0:1c358ea10753 360
spastor 0:1c358ea10753 361 if (packet_length == 0)
spastor 0:1c358ea10753 362 {
spastor 0:1c358ea10753 363 /* set to complete data since no data to be read. */
spastor 0:1c358ea10753 364 connector_ptr->edp_data.receive_packet.index = receive_packet_complete;
spastor 0:1c358ea10753 365 connector_ptr->edp_data.receive_packet.packet_length = packet_length;
spastor 0:1c358ea10753 366 connector_ptr->edp_data.receive_packet.total_length = packet_length;
spastor 0:1c358ea10753 367 }
spastor 0:1c358ea10753 368 else
spastor 0:1c358ea10753 369 {
spastor 0:1c358ea10753 370 /*
spastor 0:1c358ea10753 371 * Read the actual message data bytes into the packet buffer.
spastor 0:1c358ea10753 372 */
spastor 0:1c358ea10753 373 ASSERT(packet_length <= (sizeof connector_ptr->edp_data.receive_packet.packet_buffer.buffer - PACKET_EDP_HEADER_SIZE));
spastor 0:1c358ea10753 374
spastor 0:1c358ea10753 375 if (edp_get_active_state(connector_ptr) != connector_transport_open)
spastor 0:1c358ea10753 376 {
spastor 0:1c358ea10753 377 /* We already setup data_packet in
spastor 0:1c358ea10753 378 * receive_packet_init index. So we setup data_packet when we
spastor 0:1c358ea10753 379 * are already established the EDP.
spastor 0:1c358ea10753 380 */
spastor 0:1c358ea10753 381 connector_ptr->edp_data.receive_packet.data_packet = tcp_new_receive_packet(connector_ptr);
spastor 0:1c358ea10753 382 if (connector_ptr->edp_data.receive_packet.data_packet == NULL)
spastor 0:1c358ea10753 383 {
spastor 0:1c358ea10753 384 goto done;
spastor 0:1c358ea10753 385 }
spastor 0:1c358ea10753 386 }
spastor 0:1c358ea10753 387
spastor 0:1c358ea10753 388 connector_ptr->edp_data.receive_packet.packet_length = packet_length;
spastor 0:1c358ea10753 389 connector_ptr->edp_data.receive_packet.total_length = packet_length;
spastor 0:1c358ea10753 390
spastor 0:1c358ea10753 391 connector_ptr->edp_data.receive_packet.ptr = GET_PACKET_DATA_POINTER(connector_ptr->edp_data.receive_packet.data_packet->buffer, PACKET_EDP_HEADER_SIZE);
spastor 0:1c358ea10753 392 connector_ptr->edp_data.receive_packet.bytes_received = 0;
spastor 0:1c358ea10753 393 connector_ptr->edp_data.receive_packet.index++;
spastor 0:1c358ea10753 394
spastor 0:1c358ea10753 395 }
spastor 0:1c358ea10753 396 break;
spastor 0:1c358ea10753 397 }
spastor 0:1c358ea10753 398 case receive_packet_complete:
spastor 0:1c358ea10753 399
spastor 0:1c358ea10753 400 if (connector_ptr->edp_data.receive_packet.data_packet != NULL &&
spastor 0:1c358ea10753 401 connector_ptr->edp_data.receive_packet.packet_type != E_MSG_MT2_TYPE_KA_KEEPALIVE)
spastor 0:1c358ea10753 402 {
spastor 0:1c358ea10753 403 uint8_t * edp_header = connector_ptr->edp_data.receive_packet.data_packet->buffer;
spastor 0:1c358ea10753 404 /* got message data. Let's set edp header */
spastor 0:1c358ea10753 405 message_store_be16(edp_header, type, connector_ptr->edp_data.receive_packet.packet_type);
spastor 0:1c358ea10753 406 message_store_be16(edp_header, length, connector_ptr->edp_data.receive_packet.packet_length);
spastor 0:1c358ea10753 407 *packet = connector_ptr->edp_data.receive_packet.data_packet;
spastor 0:1c358ea10753 408 result = connector_working;
spastor 0:1c358ea10753 409 }
spastor 0:1c358ea10753 410
spastor 0:1c358ea10753 411 connector_ptr->edp_data.receive_packet.index = receive_packet_init;
spastor 0:1c358ea10753 412 goto done;
spastor 0:1c358ea10753 413 } /* switch */
spastor 0:1c358ea10753 414 }
spastor 0:1c358ea10753 415
spastor 0:1c358ea10753 416 done:
spastor 0:1c358ea10753 417 return result;
spastor 0:1c358ea10753 418 }
spastor 0:1c358ea10753 419
spastor 0:1c358ea10753 420 static connector_status_t layer_facility_process(connector_data_t * const connector_ptr);
spastor 0:1c358ea10753 421
spastor 0:1c358ea10753 422 static connector_status_t edp_tcp_receive_process(connector_data_t * connector_ptr)
spastor 0:1c358ea10753 423 {
spastor 0:1c358ea10753 424 enum {
spastor 0:1c358ea10753 425 facility_receive_message,
spastor 0:1c358ea10753 426 facility_process_message
spastor 0:1c358ea10753 427 };
spastor 0:1c358ea10753 428 connector_status_t result;
spastor 0:1c358ea10753 429
spastor 0:1c358ea10753 430 connector_buffer_t * packet_buffer = NULL;
spastor 0:1c358ea10753 431 connector_bool_t done_packet = connector_true;
spastor 0:1c358ea10753 432 connector_facility_t * fac_ptr;
spastor 0:1c358ea10753 433
spastor 0:1c358ea10753 434
spastor 0:1c358ea10753 435 /* Facility layer is the layer that the Connector has fully established
spastor 0:1c358ea10753 436 * communication with Device Cloud. It keeps waiting messages from Device Cloud
spastor 0:1c358ea10753 437 * and passes it to the appropriate facility:
spastor 0:1c358ea10753 438 * 1. waits message from Device Cloud
spastor 0:1c358ea10753 439 * 2. parses message and passes it to the facility
spastor 0:1c358ea10753 440 * 3. invokes facility to process message.
spastor 0:1c358ea10753 441 */
spastor 0:1c358ea10753 442 result = tcp_receive_packet(connector_ptr, &packet_buffer);
spastor 0:1c358ea10753 443
spastor 0:1c358ea10753 444 if (result == connector_working)
spastor 0:1c358ea10753 445 {
spastor 0:1c358ea10753 446 uint8_t * packet ;
spastor 0:1c358ea10753 447 uint8_t * edp_header;
spastor 0:1c358ea10753 448 uint8_t * edp_protocol;
spastor 0:1c358ea10753 449
spastor 0:1c358ea10753 450 ASSERT(packet_buffer != NULL);
spastor 0:1c358ea10753 451
spastor 0:1c358ea10753 452 packet = packet_buffer->buffer;
spastor 0:1c358ea10753 453 edp_header = packet;
spastor 0:1c358ea10753 454 edp_protocol = packet + PACKET_EDP_HEADER_SIZE;
spastor 0:1c358ea10753 455
spastor 0:1c358ea10753 456 /*
spastor 0:1c358ea10753 457 * received packet format:
spastor 0:1c358ea10753 458 * ----------------------------------------------------------
spastor 0:1c358ea10753 459 * | 0 - 1 | 2 - 3 | 4 | 5 | 6 - 7 | 8... |
spastor 0:1c358ea10753 460 * ----------------------------------------------------------
spastor 0:1c358ea10753 461 * | Payload | length | coding | discovery | facility | Data |
spastor 0:1c358ea10753 462 * | Type | | scheme | payload | | |
spastor 0:1c358ea10753 463 * -----------------------------------------------------------
spastor 0:1c358ea10753 464 * | EDP Header | EDP Protocol |
spastor 0:1c358ea10753 465 * -----------------------------------------------------------
spastor 0:1c358ea10753 466 */
spastor 0:1c358ea10753 467
spastor 0:1c358ea10753 468 if (message_load_be16(edp_header, type) == E_MSG_MT2_TYPE_PAYLOAD)
spastor 0:1c358ea10753 469 {
spastor 0:1c358ea10753 470 uint16_t total_length = message_load_be16(edp_header, length);
spastor 0:1c358ea10753 471 uint8_t const sec_code = message_load_u8(edp_protocol, sec_coding);
spastor 0:1c358ea10753 472 uint8_t const payload = message_load_u8(edp_protocol, payload);
spastor 0:1c358ea10753 473
spastor 0:1c358ea10753 474 /* currently we don't support any other security protocol */
spastor 0:1c358ea10753 475 ASSERT_GOTO(sec_code == SECURITY_PROTO_NONE, error);
spastor 0:1c358ea10753 476 ASSERT_GOTO(payload == DISC_OP_PAYLOAD, error);
spastor 0:1c358ea10753 477 ASSERT_GOTO(total_length > PACKET_EDP_PROTOCOL_SIZE, error);
spastor 0:1c358ea10753 478
spastor 0:1c358ea10753 479 connector_debug_printf("edp_tcp_receive_process: receive data facility = 0x%04x\n", message_load_be16(edp_protocol, facility));
spastor 0:1c358ea10753 480 /* adjust the length for facility process */
spastor 0:1c358ea10753 481 {
spastor 0:1c358ea10753 482 uint16_t const length = (uint16_t)(total_length - PACKET_EDP_PROTOCOL_SIZE);
spastor 0:1c358ea10753 483 message_store_be16(edp_header, length, length);
spastor 0:1c358ea10753 484 }
spastor 0:1c358ea10753 485
spastor 0:1c358ea10753 486 }
spastor 0:1c358ea10753 487
spastor 0:1c358ea10753 488 if (message_load_be16(edp_header, type) == E_MSG_MT2_TYPE_PAYLOAD)
spastor 0:1c358ea10753 489 {
spastor 0:1c358ea10753 490 uint16_t facility;
spastor 0:1c358ea10753 491 uint8_t * edp_protocol = packet + PACKET_EDP_HEADER_SIZE;
spastor 0:1c358ea10753 492 /* search facility
spastor 0:1c358ea10753 493 *
spastor 0:1c358ea10753 494 * Make sure the facility is not processing previous packet.
spastor 0:1c358ea10753 495 */
spastor 0:1c358ea10753 496 facility = message_load_be16(edp_protocol, facility);
spastor 0:1c358ea10753 497 for (fac_ptr = connector_ptr->edp_data.facilities.list; fac_ptr != NULL; fac_ptr = fac_ptr->next)
spastor 0:1c358ea10753 498 {
spastor 0:1c358ea10753 499 if (fac_ptr->facility_num == facility)
spastor 0:1c358ea10753 500 {
spastor 0:1c358ea10753 501 if (fac_ptr->packet_buffer == NULL)
spastor 0:1c358ea10753 502 {
spastor 0:1c358ea10753 503 fac_ptr->packet_buffer = packet_buffer;
spastor 0:1c358ea10753 504 connector_ptr->edp_data.facilities.current = fac_ptr;
spastor 0:1c358ea10753 505 done_packet = connector_false;
spastor 0:1c358ea10753 506 }
spastor 0:1c358ea10753 507 else
spastor 0:1c358ea10753 508 {
spastor 0:1c358ea10753 509 /* we only have one receive buffer.
spastor 0:1c358ea10753 510 * Since a facility holds on the receive buffer,
spastor 0:1c358ea10753 511 * receive should not able to get a free receive buffer
spastor 0:1c358ea10753 512 * to receive any data
spastor 0:1c358ea10753 513 */
spastor 0:1c358ea10753 514 ASSERT(connector_false);
spastor 0:1c358ea10753 515 }
spastor 0:1c358ea10753 516 break;
spastor 0:1c358ea10753 517 }
spastor 0:1c358ea10753 518 }
spastor 0:1c358ea10753 519 }
spastor 0:1c358ea10753 520 }
spastor 0:1c358ea10753 521 else if (result != connector_idle && result != connector_pending)
spastor 0:1c358ea10753 522 {
spastor 0:1c358ea10753 523 goto done;
spastor 0:1c358ea10753 524 }
spastor 0:1c358ea10753 525
spastor 0:1c358ea10753 526 error:
spastor 0:1c358ea10753 527 /* if we are done with packet, release it for another
spastor 0:1c358ea10753 528 * receive_packet .
spastor 0:1c358ea10753 529 */
spastor 0:1c358ea10753 530 if (done_packet && packet_buffer != NULL)
spastor 0:1c358ea10753 531 {
spastor 0:1c358ea10753 532 tcp_release_receive_packet(connector_ptr, packet_buffer);
spastor 0:1c358ea10753 533 }
spastor 0:1c358ea10753 534
spastor 0:1c358ea10753 535 /* Let's process facility */
spastor 0:1c358ea10753 536 result = layer_facility_process(connector_ptr);
spastor 0:1c358ea10753 537
spastor 0:1c358ea10753 538 done:
spastor 0:1c358ea10753 539 if (result != connector_idle && result != connector_pending && result != connector_working && result != connector_active)
spastor 0:1c358ea10753 540 {
spastor 0:1c358ea10753 541 edp_set_active_state(connector_ptr, connector_transport_close);
spastor 0:1c358ea10753 542 result = connector_working;
spastor 0:1c358ea10753 543 goto done;
spastor 0:1c358ea10753 544 }
spastor 0:1c358ea10753 545 return result;
spastor 0:1c358ea10753 546 }
spastor 0:1c358ea10753 547
spastor 0:1c358ea10753 548