Sebastián Pastor / EtheriosCloudConnector
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 #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