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 14:10:48 2013 +0000
Revision:
1:908afea5a49d
Parent:
0:1c358ea10753
Use internal Thread.h instead of Threads.h

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 #define FAC_CC_DISCONNECT 0x00
spastor 0:1c358ea10753 14 #define FAC_CC_REDIRECT_TO_SDA 0x03
spastor 0:1c358ea10753 15 #define FAC_CC_REDIRECT_REPORT 0x04
spastor 0:1c358ea10753 16 #define FAC_CC_CONNECTION_REPORT 0x05
spastor 0:1c358ea10753 17 #define FAC_CC_REBOOT 0x06
spastor 0:1c358ea10753 18
spastor 0:1c358ea10753 19 #define CC_REDIRECT_URL_COUNT 2
spastor 0:1c358ea10753 20
spastor 0:1c358ea10753 21 typedef enum {
spastor 0:1c358ea10753 22 cc_not_redirect,
spastor 0:1c358ea10753 23 cc_redirect_success,
spastor 0:1c358ea10753 24 cc_redirect_error
spastor 0:1c358ea10753 25 } cc_redirect_status_t;
spastor 0:1c358ea10753 26
spastor 0:1c358ea10753 27 typedef enum {
spastor 0:1c358ea10753 28 ethernet_type = 1,
spastor 0:1c358ea10753 29 ppp_over_modem_type
spastor 0:1c358ea10753 30 } cc_connection_type_t;
spastor 0:1c358ea10753 31
spastor 0:1c358ea10753 32 enum {
spastor 0:1c358ea10753 33 cc_state_redirect_report,
spastor 0:1c358ea10753 34 cc_state_connect_report,
spastor 0:1c358ea10753 35 cc_state_close,
spastor 0:1c358ea10753 36 cc_state_connect
spastor 0:1c358ea10753 37
spastor 0:1c358ea10753 38 };
spastor 0:1c358ea10753 39
spastor 0:1c358ea10753 40
spastor 0:1c358ea10753 41 typedef struct {
spastor 0:1c358ea10753 42 char origin_url[CLOUD_URL_LENGTH];
spastor 0:1c358ea10753 43 size_t origin_url_length;
spastor 0:1c358ea10753 44
spastor 0:1c358ea10753 45 uint8_t * redirect;
spastor 0:1c358ea10753 46
spastor 0:1c358ea10753 47 int state;
spastor 0:1c358ea10753 48 size_t redirect_count;
spastor 0:1c358ea10753 49 uint8_t report_code;
spastor 0:1c358ea10753 50 } connector_cc_data_t;
spastor 0:1c358ea10753 51
spastor 0:1c358ea10753 52 static void cc_init(connector_cc_data_t * const cc_ptr)
spastor 0:1c358ea10753 53 {
spastor 0:1c358ea10753 54 cc_ptr->state = cc_state_redirect_report;
spastor 0:1c358ea10753 55 cc_ptr->report_code = cc_not_redirect;
spastor 0:1c358ea10753 56 cc_ptr->origin_url_length = 0;
spastor 0:1c358ea10753 57
spastor 0:1c358ea10753 58 }
spastor 0:1c358ea10753 59
spastor 0:1c358ea10753 60 static connector_status_t edp_send_redirect_report(connector_data_t * const connector_ptr, connector_cc_data_t * const cc_ptr)
spastor 0:1c358ea10753 61 {
spastor 0:1c358ea10753 62
spastor 0:1c358ea10753 63 enum cc_redirect_report {
spastor 0:1c358ea10753 64 field_define(redirect_report, opcode, uint8_t),
spastor 0:1c358ea10753 65 field_define(redirect_report, code, uint8_t),
spastor 0:1c358ea10753 66 field_define(redirect_report, message_length, uint8_t),
spastor 0:1c358ea10753 67 /* TODO: Need to fix this enum if message_length > 0. For now, cloud always send message length = 0 */
spastor 0:1c358ea10753 68 field_define(redirect_report, url_length, uint16_t),
spastor 0:1c358ea10753 69 record_end(redirect_report)
spastor 0:1c358ea10753 70 };
spastor 0:1c358ea10753 71
spastor 0:1c358ea10753 72 size_t const report_message_length = 0;
spastor 0:1c358ea10753 73 size_t const redirect_report_header_size = record_bytes(redirect_report);
spastor 0:1c358ea10753 74
spastor 0:1c358ea10753 75 connector_status_t result = connector_working;
spastor 0:1c358ea10753 76 uint8_t * edp_header;
spastor 0:1c358ea10753 77 uint8_t * redirect_report;
spastor 0:1c358ea10753 78 size_t url_length;
spastor 0:1c358ea10753 79 size_t redirect_length;
spastor 0:1c358ea10753 80
spastor 0:1c358ea10753 81 ASSERT(report_message_length == 0);
spastor 0:1c358ea10753 82
spastor 0:1c358ea10753 83 connector_debug_printf("Connection Control: send redirect_report\n");
spastor 0:1c358ea10753 84
spastor 0:1c358ea10753 85 /* build and send redirect report
spastor 0:1c358ea10753 86 * ----------------------------------------------------
spastor 0:1c358ea10753 87 * | 0 | 1 | 2 | 3... | x1-x2 | ... |
spastor 0:1c358ea10753 88 * ----------------------------------------------------
spastor 0:1c358ea10753 89 * | opcode | report | message | report | url | url |
spastor 0:1c358ea10753 90 * | | code | length | message | length | |
spastor 0:1c358ea10753 91 * ----------------------------------------------------
spastor 0:1c358ea10753 92 */
spastor 0:1c358ea10753 93
spastor 0:1c358ea10753 94 edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_CC_NUM, &redirect_report, &redirect_length);
spastor 0:1c358ea10753 95 if (edp_header == NULL)
spastor 0:1c358ea10753 96 {
spastor 0:1c358ea10753 97 result = connector_pending;
spastor 0:1c358ea10753 98 goto done;
spastor 0:1c358ea10753 99 }
spastor 0:1c358ea10753 100
spastor 0:1c358ea10753 101 message_store_u8(redirect_report, opcode, FAC_CC_REDIRECT_REPORT);
spastor 0:1c358ea10753 102 message_store_u8(redirect_report, code, cc_ptr->report_code);
spastor 0:1c358ea10753 103 {
spastor 0:1c358ea10753 104 uint8_t const length8 = (uint8_t) report_message_length;
spastor 0:1c358ea10753 105
spastor 0:1c358ea10753 106 ASSERT(report_message_length <= UCHAR_MAX);
spastor 0:1c358ea10753 107 message_store_u8(redirect_report, message_length, length8);
spastor 0:1c358ea10753 108 }
spastor 0:1c358ea10753 109
spastor 0:1c358ea10753 110 url_length = cc_ptr->origin_url_length;
spastor 0:1c358ea10753 111
spastor 0:1c358ea10753 112 if (url_length > 0)
spastor 0:1c358ea10753 113 {
spastor 0:1c358ea10753 114 char const prefix_url[] = URL_PREFIX;
spastor 0:1c358ea10753 115 size_t const prefix_len = sizeof prefix_url -1;
spastor 0:1c358ea10753 116 uint8_t * const redirect_report_url = redirect_report + redirect_report_header_size;
spastor 0:1c358ea10753 117
spastor 0:1c358ea10753 118 ASSERT(redirect_length > (redirect_report_header_size + prefix_len + cc_ptr->origin_url_length));
spastor 0:1c358ea10753 119
spastor 0:1c358ea10753 120 memcpy(redirect_report_url, prefix_url, prefix_len);
spastor 0:1c358ea10753 121 memcpy((redirect_report_url + prefix_len), cc_ptr->origin_url, cc_ptr->origin_url_length);
spastor 0:1c358ea10753 122
spastor 0:1c358ea10753 123 url_length += prefix_len;
spastor 0:1c358ea10753 124
spastor 0:1c358ea10753 125 }
spastor 0:1c358ea10753 126 {
spastor 0:1c358ea10753 127 uint16_t const length16 = (uint16_t) url_length;
spastor 0:1c358ea10753 128
spastor 0:1c358ea10753 129 ASSERT(url_length <= UINT16_MAX);
spastor 0:1c358ea10753 130 message_store_be16(redirect_report, url_length, length16);
spastor 0:1c358ea10753 131 }
spastor 0:1c358ea10753 132
spastor 0:1c358ea10753 133 result = tcp_initiate_send_facility_packet(connector_ptr, edp_header,
spastor 0:1c358ea10753 134 redirect_report_header_size + url_length,
spastor 0:1c358ea10753 135 E_MSG_FAC_CC_NUM, tcp_release_packet_buffer, NULL);
spastor 0:1c358ea10753 136 done:
spastor 0:1c358ea10753 137 return result;
spastor 0:1c358ea10753 138 }
spastor 0:1c358ea10753 139
spastor 0:1c358ea10753 140 static void build_ip_addr(connector_data_t * const connector_ptr, uint8_t * ipv6_addr)
spastor 0:1c358ea10753 141 {
spastor 0:1c358ea10753 142 connector_debug_hexvalue("Send device IP address", connector_ptr->edp_data.config.ip_addr, (int) connector_ptr->edp_data.config.ip_addr_length);
spastor 0:1c358ea10753 143
spastor 0:1c358ea10753 144 if (connector_ptr->edp_data.config.ip_addr_length == CC_IPV6_ADDRESS_LENGTH)
spastor 0:1c358ea10753 145 {
spastor 0:1c358ea10753 146 /* Just copy IPv6 address */
spastor 0:1c358ea10753 147 memcpy(ipv6_addr, connector_ptr->edp_data.config.ip_addr, CC_IPV6_ADDRESS_LENGTH);
spastor 0:1c358ea10753 148 }
spastor 0:1c358ea10753 149 else
spastor 0:1c358ea10753 150 {
spastor 0:1c358ea10753 151 /* good ipv4 addr. Map ipv4 to ipv6 address:
spastor 0:1c358ea10753 152 * 10 all-zeros octets, 2 all-ones octets, and
spastor 0:1c358ea10753 153 * then the ipv4 addr
spastor 0:1c358ea10753 154 */
spastor 0:1c358ea10753 155
spastor 0:1c358ea10753 156 static unsigned char const ipv6_padding_for_ipv4[] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
spastor 0:1c358ea10753 157 size_t const padding_length = sizeof ipv6_padding_for_ipv4/sizeof ipv6_padding_for_ipv4[0];
spastor 0:1c358ea10753 158
spastor 0:1c358ea10753 159 ASSERT(padding_length == (CC_IPV6_ADDRESS_LENGTH - CC_IPV4_ADDRESS_LENGTH));
spastor 0:1c358ea10753 160
spastor 0:1c358ea10753 161 memcpy(ipv6_addr, ipv6_padding_for_ipv4, padding_length);
spastor 0:1c358ea10753 162 ipv6_addr += padding_length;
spastor 0:1c358ea10753 163 memcpy(ipv6_addr, connector_ptr->edp_data.config.ip_addr, CC_IPV4_ADDRESS_LENGTH);
spastor 0:1c358ea10753 164 }
spastor 0:1c358ea10753 165
spastor 0:1c358ea10753 166 return;
spastor 0:1c358ea10753 167
spastor 0:1c358ea10753 168 }
spastor 0:1c358ea10753 169
spastor 0:1c358ea10753 170 static connector_status_t send_connection_report(connector_data_t * const connector_ptr, connector_cc_data_t * const cc_ptr)
spastor 0:1c358ea10753 171 {
spastor 0:1c358ea10753 172 #define FAC_CC_CLIENTTYPE_REBOOTABLE_DEVICE 2
spastor 0:1c358ea10753 173
spastor 0:1c358ea10753 174 enum cc_connection_report {
spastor 0:1c358ea10753 175 field_define(connection_report, opcode, uint8_t),
spastor 0:1c358ea10753 176 field_define(connection_report, client_type, uint8_t),
spastor 0:1c358ea10753 177 field_define(connection_report, ip1, uint32_t),
spastor 0:1c358ea10753 178 field_define(connection_report, ip2, uint32_t),
spastor 0:1c358ea10753 179 field_define(connection_report, ip3, uint32_t),
spastor 0:1c358ea10753 180 field_define(connection_report, ip4, uint32_t),
spastor 0:1c358ea10753 181 field_define(connection_report, connection_type, uint8_t),
spastor 0:1c358ea10753 182 record_end(connection_report)
spastor 0:1c358ea10753 183 };
spastor 0:1c358ea10753 184
spastor 0:1c358ea10753 185 enum cc_connection_info {
spastor 0:1c358ea10753 186 field_define(connection_info, link_speed, uint32_t),
spastor 0:1c358ea10753 187 record_end(connection_info)
spastor 0:1c358ea10753 188 };
spastor 0:1c358ea10753 189 connector_status_t result = connector_working;
spastor 0:1c358ea10753 190 uint8_t * edp_header;
spastor 0:1c358ea10753 191 uint8_t * connection_report;
spastor 0:1c358ea10753 192 size_t avail_length;
spastor 0:1c358ea10753 193 size_t report_length;
spastor 0:1c358ea10753 194
spastor 0:1c358ea10753 195 UNUSED_PARAMETER(cc_ptr);
spastor 0:1c358ea10753 196
spastor 0:1c358ea10753 197 connector_debug_printf("Connection Control: send connection report\n");
spastor 0:1c358ea10753 198
spastor 0:1c358ea10753 199 /* Build Connection report
spastor 0:1c358ea10753 200 * -------------------------------------------------------
spastor 0:1c358ea10753 201 * | 0 | 1 | 2 - 17 | 18 | 19 ... |
spastor 0:1c358ea10753 202 * -------------------------------------------------------
spastor 0:1c358ea10753 203 * | opcode | client | IP | connection | connection |
spastor 0:1c358ea10753 204 * | | type | address | type | information |
spastor 0:1c358ea10753 205 * -------------------------------------------------------
spastor 0:1c358ea10753 206 *
spastor 0:1c358ea10753 207 * 1. call callback to get ip address & build ip_address
spastor 0:1c358ea10753 208 * 2. call callback to get & build connection type
spastor 0:1c358ea10753 209 * 3. if connection type is LAN, call callback to get and build mac address for connection information
spastor 0:1c358ea10753 210 * 4. if connection type is WAN, call callback to get and build link speed for connection information
spastor 0:1c358ea10753 211 * 5. if connection type is WAN, call callback to get and build phone number for connection information
spastor 0:1c358ea10753 212 */
spastor 0:1c358ea10753 213 edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_FAC_CC_NUM, &connection_report, &avail_length);
spastor 0:1c358ea10753 214 if (edp_header == NULL)
spastor 0:1c358ea10753 215 {
spastor 0:1c358ea10753 216 result = connector_pending;
spastor 0:1c358ea10753 217 goto done;
spastor 0:1c358ea10753 218 }
spastor 0:1c358ea10753 219
spastor 0:1c358ea10753 220 {
spastor 0:1c358ea10753 221 result = get_config_ip_addr(connector_ptr);
spastor 0:1c358ea10753 222
spastor 0:1c358ea10753 223 if (result != connector_working)
spastor 0:1c358ea10753 224 {
spastor 0:1c358ea10753 225 goto done;
spastor 0:1c358ea10753 226 }
spastor 0:1c358ea10753 227
spastor 0:1c358ea10753 228 message_store_u8(connection_report, opcode, FAC_CC_CONNECTION_REPORT);
spastor 0:1c358ea10753 229 message_store_u8(connection_report, client_type, FAC_CC_CLIENTTYPE_REBOOTABLE_DEVICE);
spastor 0:1c358ea10753 230 report_length = field_named_data(connection_report, opcode, size)+field_named_data(connection_report, client_type, size);
spastor 0:1c358ea10753 231
spastor 0:1c358ea10753 232 build_ip_addr(connector_ptr, (connection_report+report_length));
spastor 0:1c358ea10753 233 report_length += CC_IPV6_ADDRESS_LENGTH;
spastor 0:1c358ea10753 234
spastor 0:1c358ea10753 235 }
spastor 0:1c358ea10753 236
spastor 0:1c358ea10753 237 {
spastor 0:1c358ea10753 238 cc_connection_type_t const connection_type = (connector_ptr->connection_type == connector_connection_type_lan) ? ethernet_type : ppp_over_modem_type;
spastor 0:1c358ea10753 239
spastor 0:1c358ea10753 240 message_store_u8(connection_report, connection_type, connection_type);
spastor 0:1c358ea10753 241
spastor 0:1c358ea10753 242 report_length += field_named_data(connection_report, connection_type, size);
spastor 0:1c358ea10753 243
spastor 0:1c358ea10753 244 switch (connector_ptr->connection_type)
spastor 0:1c358ea10753 245 {
spastor 0:1c358ea10753 246 case connector_connection_type_lan:
spastor 0:1c358ea10753 247 result = get_config_mac_addr(connector_ptr);
spastor 0:1c358ea10753 248 if (result != connector_working)
spastor 0:1c358ea10753 249 {
spastor 0:1c358ea10753 250 goto done;
spastor 0:1c358ea10753 251
spastor 0:1c358ea10753 252 }
spastor 0:1c358ea10753 253
spastor 0:1c358ea10753 254 {
spastor 0:1c358ea10753 255 uint8_t * report_ptr = connection_report + report_length;
spastor 0:1c358ea10753 256
spastor 0:1c358ea10753 257 ASSERT(connector_ptr->mac_addr != NULL);
spastor 0:1c358ea10753 258 /* build MAC address for LAN connection type */
spastor 0:1c358ea10753 259 memcpy(report_ptr, connector_ptr->mac_addr, MAC_ADDR_LENGTH);
spastor 0:1c358ea10753 260 report_length += MAC_ADDR_LENGTH;
spastor 0:1c358ea10753 261
spastor 0:1c358ea10753 262 connector_debug_hexvalue("Sending MAC address", connector_ptr->mac_addr, MAC_ADDR_LENGTH);
spastor 0:1c358ea10753 263
spastor 0:1c358ea10753 264 break;
spastor 0:1c358ea10753 265 }
spastor 0:1c358ea10753 266 case connector_connection_type_wan:
spastor 0:1c358ea10753 267 {
spastor 0:1c358ea10753 268 /* build Link speed for WAN connection type */
spastor 0:1c358ea10753 269 uint8_t * connection_info = connection_report + record_bytes(connection_report);
spastor 0:1c358ea10753 270
spastor 0:1c358ea10753 271
spastor 0:1c358ea10753 272 #if (defined CONNECTOR_WAN_LINK_SPEED_IN_BITS_PER_SECOND)
spastor 0:1c358ea10753 273 message_store_be32(connection_info, link_speed, CONNECTOR_WAN_LINK_SPEED_IN_BITS_PER_SECOND);
spastor 0:1c358ea10753 274 connector_debug_printf("send_connection_report: link_speed = %d\n", CONNECTOR_WAN_LINK_SPEED_IN_BITS_PER_SECOND);
spastor 0:1c358ea10753 275
spastor 0:1c358ea10753 276 #else
spastor 0:1c358ea10753 277 message_store_be32(connection_info, link_speed, connector_ptr->link_speed);
spastor 0:1c358ea10753 278 connector_debug_printf("send_connection_report: link_speed = %d\n", connector_ptr->link_speed);
spastor 0:1c358ea10753 279 #endif
spastor 0:1c358ea10753 280 report_length += field_named_data(connection_info, link_speed, size);
spastor 0:1c358ea10753 281
spastor 0:1c358ea10753 282 {
spastor 0:1c358ea10753 283 /* build phone number for WAN connection type */
spastor 0:1c358ea10753 284
spastor 0:1c358ea10753 285 #if (defined CONNECTOR_WAN_PHONE_NUMBER_DIALED)
spastor 0:1c358ea10753 286 char const phone[] = CONNECTOR_WAN_PHONE_NUMBER_DIALED;
spastor 0:1c358ea10753 287 size_t const length = sizeof phone -1;
spastor 0:1c358ea10753 288 #else
spastor 0:1c358ea10753 289 size_t length = connector_ptr->phone_dialed_length;
spastor 0:1c358ea10753 290 char * phone = connector_ptr->phone_dialed;
spastor 0:1c358ea10753 291 #endif
spastor 0:1c358ea10753 292 connector_debug_printf("send_connection_report: phone number = %.*s\n", (int)length, phone);
spastor 0:1c358ea10753 293 memcpy(connection_report+report_length, phone, length);
spastor 0:1c358ea10753 294 report_length += length;
spastor 0:1c358ea10753 295 *(connection_report + report_length) = 0x0;
spastor 0:1c358ea10753 296 report_length++;
spastor 0:1c358ea10753 297 }
spastor 0:1c358ea10753 298 }
spastor 0:1c358ea10753 299 }
spastor 0:1c358ea10753 300 }
spastor 0:1c358ea10753 301
spastor 0:1c358ea10753 302 ASSERT(avail_length > report_length);
spastor 0:1c358ea10753 303 result = tcp_initiate_send_facility_packet(connector_ptr, edp_header, report_length, E_MSG_FAC_CC_NUM, tcp_release_packet_buffer, NULL);
spastor 0:1c358ea10753 304
spastor 0:1c358ea10753 305 done:
spastor 0:1c358ea10753 306 return result;
spastor 0:1c358ea10753 307 }
spastor 0:1c358ea10753 308
spastor 0:1c358ea10753 309
spastor 0:1c358ea10753 310 static connector_status_t process_redirect(connector_data_t * const connector_ptr, connector_cc_data_t * const cc_ptr, uint8_t const * const packet)
spastor 0:1c358ea10753 311 {
spastor 0:1c358ea10753 312 enum cc_redirect {
spastor 0:1c358ea10753 313 field_define(redirect, opcode, uint8_t),
spastor 0:1c358ea10753 314 field_define(redirect, count, uint8_t),
spastor 0:1c358ea10753 315 record_end(redirect)
spastor 0:1c358ea10753 316 };
spastor 0:1c358ea10753 317
spastor 0:1c358ea10753 318
spastor 0:1c358ea10753 319 connector_status_t result = connector_working;
spastor 0:1c358ea10753 320 uint8_t * redirect;
spastor 0:1c358ea10753 321
spastor 0:1c358ea10753 322 connector_debug_printf("process_redirect: redirect to new destination\n");
spastor 0:1c358ea10753 323 /* Redirect to new destination:
spastor 0:1c358ea10753 324 * The connector will close connection and connect to new destination. If connect
spastor 0:1c358ea10753 325 * to new destination fails, this function will returns SUCCESS to try
spastor 0:1c358ea10753 326 * connecting to the original destination.
spastor 0:1c358ea10753 327 */
spastor 0:1c358ea10753 328
spastor 0:1c358ea10753 329 /*
spastor 0:1c358ea10753 330 * parse new destinations
spastor 0:1c358ea10753 331 * --------------------------------------------------------------------
spastor 0:1c358ea10753 332 * | 0 | 1 | 2 - 3 | 4 ... | | |
spastor 0:1c358ea10753 333 * --------------------------------------------------------------------
spastor 0:1c358ea10753 334 * | opcode | URL count | URL 1 Length| URL 1 | URL 2 Length | URL 2 |
spastor 0:1c358ea10753 335 * --------------------------------------------------------------------
spastor 0:1c358ea10753 336 *
spastor 0:1c358ea10753 337 */
spastor 0:1c358ea10753 338 redirect = GET_PACKET_DATA_POINTER(packet, PACKET_EDP_FACILITY_SIZE);
spastor 0:1c358ea10753 339 cc_ptr->redirect_count = message_load_u8(redirect, count);
spastor 0:1c358ea10753 340
spastor 0:1c358ea10753 341 if (cc_ptr->redirect_count == 0)
spastor 0:1c358ea10753 342 { /* nothing to redirect */
spastor 0:1c358ea10753 343 connector_debug_printf("cc_process_redirect: redirect with no url specified\n");
spastor 0:1c358ea10753 344 result = connector_idle;
spastor 0:1c358ea10753 345 goto done;
spastor 0:1c358ea10753 346 }
spastor 0:1c358ea10753 347
spastor 0:1c358ea10753 348 if (cc_ptr->redirect_count > CC_REDIRECT_URL_COUNT)
spastor 0:1c358ea10753 349 {
spastor 0:1c358ea10753 350 cc_ptr->redirect_count = CC_REDIRECT_URL_COUNT;
spastor 0:1c358ea10753 351 }
spastor 0:1c358ea10753 352
spastor 0:1c358ea10753 353
spastor 0:1c358ea10753 354 /* let's start parsing url length and url string */
spastor 0:1c358ea10753 355 redirect += record_bytes(redirect);
spastor 0:1c358ea10753 356 cc_ptr->redirect = redirect;
spastor 0:1c358ea10753 357
spastor 0:1c358ea10753 358 /* save original Device Cloud url that we connected before */
spastor 0:1c358ea10753 359 memcpy(cc_ptr->origin_url, connector_ptr->edp_data.config.cloud_url, connector_ptr->edp_data.config.cloud_url_length);
spastor 0:1c358ea10753 360 cc_ptr->origin_url_length = connector_ptr->edp_data.config.cloud_url_length;
spastor 0:1c358ea10753 361
spastor 0:1c358ea10753 362 /* Close the connection before parsing new destination url */
spastor 0:1c358ea10753 363 edp_set_active_state(connector_ptr, connector_transport_redirect);
spastor 0:1c358ea10753 364 cc_ptr->state = cc_state_close;
spastor 0:1c358ea10753 365
spastor 0:1c358ea10753 366 done:
spastor 0:1c358ea10753 367 return result;
spastor 0:1c358ea10753 368 }
spastor 0:1c358ea10753 369
spastor 0:1c358ea10753 370 static connector_status_t cc_process(connector_data_t * const connector_ptr, void * const facility_data,
spastor 0:1c358ea10753 371 uint8_t * const packet, unsigned int * const receive_timeout)
spastor 0:1c358ea10753 372 {
spastor 0:1c358ea10753 373 connector_status_t result = connector_idle;
spastor 0:1c358ea10753 374
spastor 0:1c358ea10753 375 UNUSED_PARAMETER(receive_timeout);
spastor 0:1c358ea10753 376
spastor 0:1c358ea10753 377 /* process incoming message from Device Cloud for Connection Control facility */
spastor 0:1c358ea10753 378 if (packet != NULL)
spastor 0:1c358ea10753 379 {
spastor 0:1c358ea10753 380 uint8_t opcode;
spastor 0:1c358ea10753 381 uint8_t * ptr;
spastor 0:1c358ea10753 382 connector_cc_data_t * cc_ptr = facility_data;
spastor 0:1c358ea10753 383
spastor 0:1c358ea10753 384 /* get the DATA portion of the packet */
spastor 0:1c358ea10753 385 ptr = GET_PACKET_DATA_POINTER(packet, PACKET_EDP_FACILITY_SIZE);
spastor 0:1c358ea10753 386 opcode = *ptr;
spastor 0:1c358ea10753 387
spastor 0:1c358ea10753 388 switch (opcode)
spastor 0:1c358ea10753 389 {
spastor 0:1c358ea10753 390
spastor 0:1c358ea10753 391 case FAC_CC_DISCONNECT:
spastor 0:1c358ea10753 392 {
spastor 0:1c358ea10753 393
spastor 0:1c358ea10753 394 edp_set_close_status(connector_ptr, connector_close_status_cloud_disconnected);
spastor 0:1c358ea10753 395 edp_set_active_state(connector_ptr, connector_transport_close);
spastor 0:1c358ea10753 396 result = connector_working;
spastor 0:1c358ea10753 397 break;
spastor 0:1c358ea10753 398 }
spastor 0:1c358ea10753 399 case FAC_CC_REDIRECT_TO_SDA:
spastor 0:1c358ea10753 400 result = process_redirect(connector_ptr, cc_ptr, packet);
spastor 0:1c358ea10753 401 break;
spastor 0:1c358ea10753 402 case FAC_CC_REBOOT:
spastor 0:1c358ea10753 403 result = connector_reboot(connector_ptr);
spastor 0:1c358ea10753 404 break;
spastor 0:1c358ea10753 405 default:
spastor 0:1c358ea10753 406 connector_debug_printf("connector_cc_process: unsupported opcode %u\n", opcode);
spastor 0:1c358ea10753 407 break;
spastor 0:1c358ea10753 408 }
spastor 0:1c358ea10753 409 }
spastor 0:1c358ea10753 410
spastor 0:1c358ea10753 411 return result;
spastor 0:1c358ea10753 412 }
spastor 0:1c358ea10753 413 static connector_status_t cc_discovery(connector_data_t * const connector_ptr, void * const facility_data,
spastor 0:1c358ea10753 414 uint8_t * const packet, unsigned int * receive_timeout)
spastor 0:1c358ea10753 415 {
spastor 0:1c358ea10753 416 connector_status_t result = connector_idle;
spastor 0:1c358ea10753 417 connector_cc_data_t * cc_ptr = facility_data;
spastor 0:1c358ea10753 418
spastor 0:1c358ea10753 419 UNUSED_PARAMETER(receive_timeout);
spastor 0:1c358ea10753 420 UNUSED_PARAMETER(packet);
spastor 0:1c358ea10753 421 /* Connection control facility needs to send redirect and
spastor 0:1c358ea10753 422 * connection reports on discovery layer.
spastor 0:1c358ea10753 423 */
spastor 0:1c358ea10753 424 if (cc_ptr->state == cc_state_redirect_report)
spastor 0:1c358ea10753 425 {
spastor 0:1c358ea10753 426 result = edp_send_redirect_report(connector_ptr, cc_ptr);
spastor 0:1c358ea10753 427 if (result == connector_working)
spastor 0:1c358ea10753 428 {
spastor 0:1c358ea10753 429 result = connector_pending; /* still not complete cc_discovery */
spastor 0:1c358ea10753 430 cc_ptr->report_code = cc_not_redirect;
spastor 0:1c358ea10753 431 cc_ptr->origin_url_length = 0;
spastor 0:1c358ea10753 432 cc_ptr->state = cc_state_connect_report;
spastor 0:1c358ea10753 433 }
spastor 0:1c358ea10753 434 }
spastor 0:1c358ea10753 435 else if (cc_ptr->state == cc_state_connect_report)
spastor 0:1c358ea10753 436 {
spastor 0:1c358ea10753 437 result = send_connection_report(connector_ptr, cc_ptr);
spastor 0:1c358ea10753 438 }
spastor 0:1c358ea10753 439
spastor 0:1c358ea10753 440 return result;
spastor 0:1c358ea10753 441 }
spastor 0:1c358ea10753 442
spastor 0:1c358ea10753 443 static connector_status_t connector_facility_cc_cleanup(connector_data_t * const connector_ptr)
spastor 0:1c358ea10753 444 {
spastor 0:1c358ea10753 445 connector_status_t result = connector_working;
spastor 0:1c358ea10753 446 connector_cc_data_t * const cc_ptr = get_facility_data(connector_ptr, E_MSG_FAC_CC_NUM);
spastor 0:1c358ea10753 447 if (cc_ptr != NULL && cc_ptr->state != cc_state_close)
spastor 0:1c358ea10753 448 {
spastor 0:1c358ea10753 449 cc_ptr->state = cc_state_redirect_report;
spastor 0:1c358ea10753 450 cc_ptr->report_code = cc_not_redirect;
spastor 0:1c358ea10753 451 cc_ptr->origin_url_length = 0;
spastor 0:1c358ea10753 452 cc_ptr->redirect_count = 0;
spastor 0:1c358ea10753 453 }
spastor 0:1c358ea10753 454
spastor 0:1c358ea10753 455 return result;
spastor 0:1c358ea10753 456 }
spastor 0:1c358ea10753 457
spastor 0:1c358ea10753 458 static connector_status_t connector_facility_cc_delete(connector_data_t * const connector_ptr)
spastor 0:1c358ea10753 459 {
spastor 0:1c358ea10753 460 return del_facility_data(connector_ptr, E_MSG_FAC_CC_NUM);
spastor 0:1c358ea10753 461 }
spastor 0:1c358ea10753 462
spastor 0:1c358ea10753 463 static connector_status_t connector_facility_cc_init(connector_data_t * const connector_ptr, unsigned int const facility_index)
spastor 0:1c358ea10753 464 {
spastor 0:1c358ea10753 465 connector_status_t result = connector_working;
spastor 0:1c358ea10753 466 connector_cc_data_t * cc_ptr;
spastor 0:1c358ea10753 467
spastor 0:1c358ea10753 468 /* Add Connection control facility
spastor 0:1c358ea10753 469 *
spastor 0:1c358ea10753 470 * Make sure connection control is not already created. If Connection
spastor 0:1c358ea10753 471 * control facility is already created, we probably reconnect to Device Cloud
spastor 0:1c358ea10753 472 * so just need to reset to initial state.
spastor 0:1c358ea10753 473 *
spastor 0:1c358ea10753 474 */
spastor 0:1c358ea10753 475 cc_ptr = get_facility_data(connector_ptr, E_MSG_FAC_CC_NUM);
spastor 0:1c358ea10753 476 if (cc_ptr == NULL)
spastor 0:1c358ea10753 477 {
spastor 0:1c358ea10753 478 void * ptr;
spastor 0:1c358ea10753 479
spastor 0:1c358ea10753 480 result = add_facility_data(connector_ptr, facility_index, E_MSG_FAC_CC_NUM, &ptr, sizeof *cc_ptr);
spastor 0:1c358ea10753 481
spastor 0:1c358ea10753 482 if (result != connector_working || ptr == NULL)
spastor 0:1c358ea10753 483 {
spastor 0:1c358ea10753 484 goto done;
spastor 0:1c358ea10753 485 }
spastor 0:1c358ea10753 486 cc_ptr = ptr;
spastor 0:1c358ea10753 487
spastor 0:1c358ea10753 488 cc_init(cc_ptr);
spastor 0:1c358ea10753 489 }
spastor 0:1c358ea10753 490
spastor 0:1c358ea10753 491 done:
spastor 0:1c358ea10753 492 return result;
spastor 0:1c358ea10753 493 }
spastor 0:1c358ea10753 494
spastor 0:1c358ea10753 495 static connector_status_t edp_redirect_process(connector_data_t * const connector_ptr)
spastor 0:1c358ea10753 496 {
spastor 0:1c358ea10753 497
spastor 0:1c358ea10753 498 connector_status_t result = connector_working;
spastor 0:1c358ea10753 499
spastor 0:1c358ea10753 500
spastor 0:1c358ea10753 501 connector_cc_data_t * const cc_ptr = get_facility_data(connector_ptr, E_MSG_FAC_CC_NUM);
spastor 0:1c358ea10753 502 ASSERT(cc_ptr != NULL);
spastor 0:1c358ea10753 503
spastor 0:1c358ea10753 504 switch (cc_ptr->state)
spastor 0:1c358ea10753 505 {
spastor 0:1c358ea10753 506 case cc_state_close:
spastor 0:1c358ea10753 507
spastor 0:1c358ea10753 508 /* set the reason for closing */
spastor 0:1c358ea10753 509 edp_set_close_status(connector_ptr, connector_close_status_cloud_redirected);
spastor 0:1c358ea10753 510
spastor 0:1c358ea10753 511 result = tcp_close_cloud(connector_ptr);
spastor 0:1c358ea10753 512 if (result == connector_working)
spastor 0:1c358ea10753 513 {
spastor 0:1c358ea10753 514 if (edp_get_active_state(connector_ptr) == connector_transport_idle)
spastor 0:1c358ea10753 515 {
spastor 0:1c358ea10753 516 /* continue to redirect state */
spastor 0:1c358ea10753 517 edp_set_active_state(connector_ptr, connector_transport_redirect);
spastor 0:1c358ea10753 518 cc_ptr->state = cc_state_connect;
spastor 0:1c358ea10753 519 goto done;
spastor 0:1c358ea10753 520 }
spastor 0:1c358ea10753 521 }
spastor 0:1c358ea10753 522
spastor 0:1c358ea10753 523 if (result != connector_pending && result != connector_abort && result != connector_device_terminated)
spastor 0:1c358ea10753 524 {
spastor 0:1c358ea10753 525 /* reset initial value */
spastor 0:1c358ea10753 526 cc_init(cc_ptr);
spastor 0:1c358ea10753 527 }
spastor 0:1c358ea10753 528 break;
spastor 0:1c358ea10753 529
spastor 0:1c358ea10753 530 case cc_state_connect:
spastor 0:1c358ea10753 531
spastor 0:1c358ea10753 532 /* let parse url length and url string */
spastor 0:1c358ea10753 533 if (cc_ptr->redirect_count > 0)
spastor 0:1c358ea10753 534 {
spastor 0:1c358ea10753 535 enum cc_redirect_url {
spastor 0:1c358ea10753 536 field_define(redirect, url_length, uint16_t),
spastor 0:1c358ea10753 537 record_end(redirect_url_length)
spastor 0:1c358ea10753 538 };
spastor 0:1c358ea10753 539
spastor 0:1c358ea10753 540 uint8_t * redirect = cc_ptr->redirect;
spastor 0:1c358ea10753 541 char const * cloud_url;
spastor 0:1c358ea10753 542 uint16_t cloud_url_length;
spastor 0:1c358ea10753 543
spastor 0:1c358ea10753 544 uint16_t const url_length = message_load_be16(redirect, url_length);
spastor 0:1c358ea10753 545 redirect += record_bytes(redirect_url_length);
spastor 0:1c358ea10753 546
spastor 0:1c358ea10753 547 {
spastor 0:1c358ea10753 548 size_t const prefix_len = sizeof URL_PREFIX -1;
spastor 0:1c358ea10753 549
spastor 0:1c358ea10753 550 cloud_url = (char const *)redirect;
spastor 0:1c358ea10753 551 cloud_url_length = url_length;
spastor 0:1c358ea10753 552
spastor 0:1c358ea10753 553 if (memcmp(cloud_url, URL_PREFIX, prefix_len) == 0)
spastor 0:1c358ea10753 554 {
spastor 0:1c358ea10753 555 cloud_url += prefix_len;
spastor 0:1c358ea10753 556 cloud_url_length -= (uint16_t) prefix_len;
spastor 0:1c358ea10753 557 }
spastor 0:1c358ea10753 558
spastor 0:1c358ea10753 559 ASSERT(cloud_url_length < sizeof connector_ptr->edp_data.config.cloud_url);
spastor 0:1c358ea10753 560 ASSERT(cloud_url_length != 0);
spastor 0:1c358ea10753 561
spastor 0:1c358ea10753 562 memcpy(connector_ptr->edp_data.config.cloud_url, cloud_url, cloud_url_length);
spastor 0:1c358ea10753 563 connector_ptr->edp_data.config.cloud_url_length = cloud_url_length;
spastor 0:1c358ea10753 564 connector_ptr->edp_data.config.cloud_url[cloud_url_length] = 0x0;
spastor 0:1c358ea10753 565
spastor 0:1c358ea10753 566 result = connect_to_cloud(connector_ptr, connector_ptr->edp_data.config.cloud_url);
spastor 0:1c358ea10753 567 }
spastor 0:1c358ea10753 568
spastor 0:1c358ea10753 569 if (result == connector_working)
spastor 0:1c358ea10753 570 {
spastor 0:1c358ea10753 571 cc_ptr->report_code = cc_redirect_success;
spastor 0:1c358ea10753 572 cc_ptr->state = cc_state_redirect_report;
spastor 0:1c358ea10753 573 edp_set_active_state(connector_ptr, connector_transport_open);
spastor 0:1c358ea10753 574 edp_set_edp_state(connector_ptr, edp_communication_send_version);
spastor 0:1c358ea10753 575
spastor 0:1c358ea10753 576 connector_ptr->edp_data.send_packet.packet_buffer.in_use = connector_false;
spastor 0:1c358ea10753 577 connector_ptr->edp_data.receive_packet.packet_buffer.in_use = connector_false;
spastor 0:1c358ea10753 578 connector_ptr->edp_data.receive_packet.packet_buffer.next = NULL;
spastor 0:1c358ea10753 579 connector_ptr->edp_data.receive_packet.free_packet_buffer = &connector_ptr->edp_data.receive_packet.packet_buffer;
spastor 0:1c358ea10753 580 }
spastor 0:1c358ea10753 581 else if (result != connector_pending && result != connector_abort)
spastor 0:1c358ea10753 582 {
spastor 0:1c358ea10753 583 /* connect to next redirect url */
spastor 0:1c358ea10753 584 result = connector_pending;
spastor 0:1c358ea10753 585 cc_ptr->redirect = redirect;
spastor 0:1c358ea10753 586 cc_ptr->redirect += url_length;
spastor 0:1c358ea10753 587 cc_ptr->redirect_count--;
spastor 0:1c358ea10753 588 }
spastor 0:1c358ea10753 589 }
spastor 0:1c358ea10753 590 else
spastor 0:1c358ea10753 591 {
spastor 0:1c358ea10753 592 cc_ptr->report_code = cc_redirect_error;
spastor 0:1c358ea10753 593 cc_ptr->state = cc_state_redirect_report;
spastor 0:1c358ea10753 594 edp_set_active_state(connector_ptr, connector_transport_open);
spastor 0:1c358ea10753 595 /* restore the original url */
spastor 0:1c358ea10753 596 edp_get_device_cloud(connector_ptr);
spastor 0:1c358ea10753 597 }
spastor 0:1c358ea10753 598 break;
spastor 0:1c358ea10753 599 }
spastor 0:1c358ea10753 600
spastor 0:1c358ea10753 601 done:
spastor 0:1c358ea10753 602 return result;
spastor 0:1c358ea10753 603 }
spastor 0:1c358ea10753 604