Sebastián Pastor / EtheriosCloudConnector
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers connector_tcp_open.h Source File

connector_tcp_open.h

00001 /*
00002  * Copyright (c) 2013 Digi International Inc.,
00003  * All rights not expressly granted are reserved.
00004  *
00005  * This Source Code Form is subject to the terms of the Mozilla Public
00006  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
00007  * You can obtain one at http://mozilla.org/MPL/2.0/.
00008  *
00009  * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
00010  * =======================================================================
00011  */
00012 
00013 static connector_status_t connect_to_cloud(connector_data_t * const connector_ptr, char const * cloud_url)
00014 {
00015     connector_status_t result = connector_working;
00016 
00017     connector_callback_status_t status;
00018     connector_network_open_t open_data;
00019 
00020     connector_request_id_t request_id;
00021 
00022     open_data.device_cloud_url = cloud_url;
00023     open_data.handle = NULL;
00024 
00025     request_id.network_request = connector_request_id_network_open;
00026     status = connector_callback(connector_ptr->callback, connector_class_id_network_tcp, request_id, &open_data);
00027     ASSERT(status != connector_callback_unrecognized);
00028     switch (status)
00029     {
00030     case connector_callback_continue:
00031         connector_ptr->edp_data.network_handle = open_data.handle;
00032         break;
00033     case  connector_callback_abort:
00034         result = connector_abort;
00035         break;
00036 
00037     case connector_callback_unrecognized:
00038         result = connector_unavailable;
00039         break;
00040 
00041     case connector_callback_error:
00042         result = connector_open_error;
00043         break;
00044     case connector_callback_busy:
00045         result = connector_pending;
00046         break;
00047     }
00048 
00049     return result;
00050 }
00051 
00052 static connector_status_t send_version(connector_data_t * connector_ptr, uint16_t const type, uint32_t const version)
00053 {
00054 enum edp_version {
00055     field_define(edp_version, version, uint32_t),
00056     record_end(edp_version)
00057 };
00058     size_t const version_message_size = record_bytes(edp_version);
00059 
00060     connector_status_t result = connector_pending;
00061     uint8_t * edp_version;
00062     uint8_t * packet;
00063 
00064     /*
00065      *  version packet format:
00066      *  -------------------------
00067      * | 0 - 1 | 2 - 3 |  4 - 7  |
00068      *  -------------------------
00069      * |  EDP header   | version |
00070      *  -------------------------
00071     */
00072 
00073     packet = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &edp_version, NULL);
00074     if (packet != NULL)
00075     {
00076         message_store_be32(edp_version, version, version);
00077 
00078         result = tcp_initiate_send_packet(connector_ptr, packet, version_message_size,
00079                                     type,
00080                                     tcp_release_packet_buffer,
00081                                     NULL);
00082     }
00083 
00084     return result;
00085 }
00086 
00087 static connector_status_t receive_edp_version(connector_data_t * const connector_ptr)
00088 {
00089 #define CLOUD_OVERLOAD_RESPONSE    0x02
00090 
00091     connector_status_t result;
00092     uint8_t * ptr;
00093     connector_buffer_t * packet_buffer;
00094 
00095     result = tcp_receive_packet(connector_ptr, &packet_buffer);
00096 
00097     if (result == connector_working && packet_buffer != NULL)
00098     {
00099         uint16_t type;
00100         uint8_t  response_code;
00101         uint8_t * const packet = packet_buffer->buffer;
00102 
00103         connector_debug_printf("Receive Mt version\n");
00104         /*
00105          * MT version response packet format:
00106          *  ---------------
00107          * |0 - 1 |  2 - 3 |
00108          *  ---------------
00109          * | Type | length |
00110          *  ---------------
00111          *
00112          */
00113 
00114         ptr = GET_PACKET_DATA_POINTER(packet, PACKET_EDP_HEADER_SIZE);
00115         {
00116             uint8_t * edp_header = packet;
00117             type = message_load_be16(edp_header, type);
00118         }
00119         response_code = *ptr;
00120 
00121         tcp_release_receive_packet(connector_ptr, packet_buffer);
00122         if (type != E_MSG_MT2_TYPE_VERSION_OK)
00123         {
00124             /*
00125              * The received message is not acceptable.
00126              */
00127             switch (type)
00128             {
00129                 /* Expected MTv2 message types... */
00130                 case E_MSG_MT2_TYPE_LEGACY_EDP_VER_RESP:
00131                     if (response_code == CLOUD_OVERLOAD_RESPONSE) {
00132                         connector_debug_printf("receive_edp_version: MTv2 legacy Cloud responded with overload msg\n");
00133                     }
00134                     else {
00135                         connector_debug_printf("receive_edp_version: MTv2 legacy bad version\n");
00136                     }
00137                     break;
00138                 case E_MSG_MT2_TYPE_VERSION_BAD:
00139                     connector_debug_printf("receive_edp_version: bad version\n");
00140                     break;
00141                 case E_MSG_MT2_TYPE_CLOUD_OVERLOAD:
00142                     connector_debug_printf("receive_edp_version: Device Cloud responded with overload msg\n");
00143                     break;
00144                 /* Unexpected/unknown MTv2 message types... */
00145                 default:
00146                     connector_debug_printf("receive_edp_version: unknown MTv2 message\n");
00147             }
00148             /* mt version error. let's notify user.
00149              *
00150              * ignore error status callback return value since Device Cloud
00151              * will close the connection.
00152              */
00153             result = connector_abort;
00154         }
00155     }
00156     else if (result == connector_idle) result = connector_pending;
00157 
00158     return result;
00159 }
00160 
00161 static size_t build_keepalive_param(uint8_t * const edp_header, uint16_t const type, uint16_t const value)
00162 {
00163 enum edp_keepalive{
00164     field_define(edp_keepalive, interval, uint16_t),
00165     record_end(edp_keepalive)
00166 };
00167 
00168     size_t const keepalive_size = record_bytes(edp_keepalive);
00169     uint8_t * edp_keepalive;
00170 
00171     edp_keepalive = GET_PACKET_DATA_POINTER(edp_header, PACKET_EDP_HEADER_SIZE);
00172     message_store_be16(edp_header, type, type);
00173     {
00174         uint16_t const keepalive_size16 = (uint16_t) keepalive_size;
00175 
00176         ASSERT(keepalive_size <= UINT16_MAX);
00177         message_store_be16(edp_header, length, keepalive_size16);
00178     }
00179     message_store_be16(edp_keepalive, interval, value);
00180 
00181 
00182     return (PACKET_EDP_HEADER_SIZE + keepalive_size); /* return count of bytes added to buffer */
00183 }
00184 
00185 static connector_status_t send_keepalive(connector_data_t * const connector_ptr)
00186 {
00187     connector_status_t result = connector_working;
00188 
00189     uint8_t * ptr;
00190     uint8_t * packet;
00191     uint8_t * start_ptr;
00192     size_t i;
00193 
00194     struct {
00195         uint16_t type;
00196         uint16_t value;
00197     } keepalive_parameters[3];
00198 
00199 #define init_param(i, t, v) keepalive_parameters[i].type = (t); keepalive_parameters[i].value = (v)
00200     init_param(0, E_MSG_MT2_TYPE_KA_RX_INTERVAL, GET_RX_KEEPALIVE_INTERVAL(connector_ptr));
00201     init_param(1, E_MSG_MT2_TYPE_KA_TX_INTERVAL, GET_TX_KEEPALIVE_INTERVAL(connector_ptr));
00202     init_param(2, E_MSG_MT2_TYPE_KA_WAIT,        GET_WAIT_COUNT(connector_ptr));
00203 #undef  init_param
00204 
00205     connector_debug_printf("Send keepalive params \n");
00206     connector_debug_printf("Rx keepalive parameter = %d\n", keepalive_parameters[0].value);
00207     connector_debug_printf("Tx keepalive parameter = %d\n", keepalive_parameters[1].value);
00208     connector_debug_printf("Wait Count parameter = %d\n", keepalive_parameters[2].value);
00209 
00210     packet = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &ptr, NULL);
00211     if (packet == NULL)
00212     {
00213         result = connector_pending;
00214         goto  done;
00215     }
00216     ptr = (uint8_t *)packet;
00217     start_ptr = ptr;
00218 
00219     for (i=0; i < asizeof(keepalive_parameters); i++)
00220     {
00221         size_t const len = build_keepalive_param(ptr, keepalive_parameters[i].type, keepalive_parameters[i].value);
00222         ptr += len;
00223     }
00224     /* Setting the total_length will enable tcp_send_packet_process.
00225      * Clear length to 0 for actual length that has been sent.
00226      */
00227     {
00228         size_t const total_packet_length = (size_t)(ptr - start_ptr);
00229         ASSERT(ptr > start_ptr);
00230         connector_ptr->edp_data.send_packet.total_length = total_packet_length;
00231         connector_ptr->edp_data.send_packet.bytes_sent = 0;
00232         connector_ptr->edp_data.send_packet.ptr = packet;
00233         connector_ptr->edp_data.send_packet.complete_cb = tcp_release_packet_buffer;
00234     }
00235 
00236 done:
00237     return result;
00238 }
00239 
00240 static connector_status_t receive_protocol_version(connector_data_t * const connector_ptr)
00241 {
00242     enum {
00243         initialization_version_response_acceptable,
00244         initialization_version_response_unacceptable,
00245         initialization_version_response_unavailable
00246     };
00247 
00248     connector_status_t result;
00249     connector_buffer_t * packet_buffer;
00250 
00251     result = tcp_receive_packet(connector_ptr, &packet_buffer);
00252 
00253     if (result == connector_working)
00254     {
00255         uint8_t * edp_header;
00256 
00257         ASSERT(packet_buffer != NULL);
00258 
00259         edp_header = packet_buffer->buffer;
00260 
00261         connector_debug_printf("Receive protocol version\n");
00262         /*
00263          *  version response packet format:
00264          *  ---------------------------------------
00265          * |    0 - 1     |  2 - 3 |     4         |
00266          *  ---------------------------------------
00267          * | Payload Type | length | response code |
00268          *  ----------------------------------------
00269         */
00270         /*
00271          * Empty data packet
00272          */
00273         if (message_load_be16(edp_header, length) > 0)
00274         {
00275             uint8_t * const response_code = GET_PACKET_DATA_POINTER(edp_header, PACKET_EDP_HEADER_SIZE);
00276             /* Parse the version response (0 = version response ok).
00277              * If the protocol version number was not acceptable to Device Cloud,
00278              * tell the application.
00279              */
00280             if (*response_code != initialization_version_response_acceptable)
00281             {
00282                 edp_set_close_status(connector_ptr, connector_close_status_abort);
00283                 connector_debug_printf("receive_protocol_version:version is not accepted by Device Cloud\n");
00284                 edp_set_active_state(connector_ptr, connector_transport_close);
00285             }
00286         }
00287 
00288         tcp_release_receive_packet(connector_ptr, packet_buffer);
00289     }
00290     else if (result == connector_idle) result = connector_pending;
00291 
00292     return result;
00293 }
00294 
00295 static connector_status_t send_identity_verification(connector_data_t * const connector_ptr)
00296 {
00297     /* The security operations other than encryption... */
00298     #define SECURITY_OPER_IDENT_FORM     UINT32_C(0x80)
00299 
00300     /* Identity verification form codes... */
00301     #define SECURITY_IDENT_FORM_SIMPLE   UINT32_C(0x00) /* simple verification */
00302     #define SECURITY_IDENT_FORM_PASSWORD UINT32_C(0x02) /* password verification */
00303 
00304     enum edp_security {
00305         field_define(edp_security, opcode, uint8_t),
00306         field_define(edp_security, identity, uint8_t),
00307         record_end(edp_security)
00308     };
00309 
00310     connector_status_t result;
00311     size_t const edp_security_size = record_bytes(edp_security);
00312     uint8_t * edp_security;
00313     uint8_t * edp_header;
00314     uint8_t identity = SECURITY_IDENT_FORM_SIMPLE;
00315 
00316     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &edp_security, NULL);
00317     if (edp_header == NULL)
00318     {
00319         result = connector_pending;
00320         goto done;
00321     }
00322 
00323 
00324     connector_debug_printf("Send identity verification\n");
00325 
00326     /*
00327      * packet format:
00328      *  -----------------------------------------------------
00329      * | 0 - 1 | 2 - 3 |     4       |     5                 |
00330      *  -----------------------------------------------------
00331      * |   EDP header  | Form opcode | identity verification |
00332      *  -----------------------------------------------------
00333     */
00334     message_store_u8(edp_security, opcode, SECURITY_OPER_IDENT_FORM);
00335 
00336     {
00337 
00338 #if (defined CONNECTOR_IDENTITY_VERIFICATION)
00339         connector_identity_verification_t const identity_verification = CONNECTOR_IDENTITY_VERIFICATION;
00340 #else
00341         connector_identity_verification_t const identity_verification = connector_ptr->edp_data.config.identity_verification;
00342 #endif
00343 
00344         switch (identity_verification)
00345         {
00346         case connector_identity_verification_simple:
00347             identity = SECURITY_IDENT_FORM_SIMPLE;
00348             break;
00349         case connector_identity_verification_password:
00350             identity = SECURITY_IDENT_FORM_PASSWORD;
00351             break;
00352         }
00353     }
00354 
00355     message_store_u8(edp_security, identity, identity);
00356 
00357     result = tcp_initiate_send_packet(connector_ptr, edp_header, edp_security_size,
00358                                 E_MSG_MT2_TYPE_PAYLOAD,
00359                                 tcp_release_packet_buffer,
00360                                 NULL);
00361 
00362 done:
00363     return result;
00364 }
00365 
00366 #if (CONNECTOR_VERSION >= 0x02010000)
00367 static connector_status_t send_provisioning(connector_data_t * const connector_ptr)
00368 {
00369     #define SECURITY_OPER_PROVISION_ID      0x89
00370     #define PROVISION_ID_LENGTH             4
00371 
00372     enum edp_device_id {
00373         field_define(edp_provision_id, opcode, uint8_t),
00374         field_define(edp_provision_id, provision_id, uint32_t),
00375         record_end(edp_provision_id)
00376     };
00377 
00378     connector_status_t result;
00379     uint8_t * edp_header;
00380     uint8_t * edp_provision_id;
00381     size_t const provision_id_message_size = record_bytes(edp_provision_id);
00382 
00383     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &edp_provision_id, NULL);
00384     if (edp_header == NULL)
00385     {
00386         result = connector_pending;
00387         goto done;
00388     }
00389 
00390     /*
00391      * packet format:
00392      *  -------------------------------------------------------
00393      * | 0 - 1 | 2 - 3 |        4                  |   5 - 8   |
00394      *  -------------------------------------------------------
00395      * |   EDP header  | Provision ID opcode | Provision ID ID |
00396      *  -------------------------------------------------------
00397     */
00398     message_store_u8(edp_provision_id, opcode, SECURITY_OPER_PROVISION_ID);
00399 
00400 #if !(defined CONNECTOR_VENDOR_ID)
00401     ASSERT(connector_ptr->edp_data.config.vendor_id != 0);
00402     message_store_be32(edp_provision_id, provision_id, connector_ptr->edp_data.config.vendor_id);
00403 #else
00404     message_store_be32(edp_provision_id, provision_id, CONNECTOR_VENDOR_ID);
00405 #endif
00406 
00407     result = tcp_initiate_send_packet(connector_ptr, edp_header, provision_id_message_size,
00408                                 E_MSG_MT2_TYPE_PAYLOAD, tcp_release_packet_buffer,
00409                                 NULL);
00410     done:
00411     return result;
00412 }
00413 #endif
00414 
00415 static connector_status_t send_device_id(connector_data_t * const connector_ptr)
00416 {
00417     #define SECURITY_OPER_DEVICE_ID      0x81
00418 
00419     enum edp_device_id {
00420         field_define(edp_device_id, opcode, uint8_t),
00421         field_define_array(edp_device_id, id, DEVICE_ID_LENGTH),
00422         record_end(edp_device_id)
00423     };
00424 
00425     connector_status_t result;
00426     uint8_t * edp_header;
00427     uint8_t * edp_device_id;
00428     size_t const device_id_message_size = record_bytes(edp_device_id);
00429 
00430     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &edp_device_id, NULL);
00431     if (edp_header == NULL)
00432     {
00433         result = connector_pending;
00434         goto done;
00435     }
00436 
00437     /*
00438      * packet format:
00439      *  ----------------------------------------------
00440      * | 0 - 1 | 2 - 3 |        4         |  5 - 20   |
00441      *  ----------------------------------------------
00442      * |   EDP header  | Device ID opcode | Device ID |
00443      *  ----------------------------------------------
00444     */
00445     message_store_u8(edp_device_id, opcode, SECURITY_OPER_DEVICE_ID);
00446 
00447     ASSERT(connector_ptr->device_id != NULL);
00448     memcpy((edp_device_id + field_named_data(edp_device_id, id, offset)), connector_ptr->device_id, DEVICE_ID_LENGTH);
00449 
00450     connector_debug_hexvalue("Sending Device ID", connector_ptr->device_id, DEVICE_ID_LENGTH);
00451 
00452     result = tcp_initiate_send_packet(connector_ptr, edp_header, device_id_message_size,
00453                                 E_MSG_MT2_TYPE_PAYLOAD, tcp_release_packet_buffer,
00454                                 NULL);
00455 done:
00456     return result;
00457 }
00458 
00459 #if (CONNECTOR_VERSION >= 0x02010000)
00460 static connector_status_t receive_device_id(connector_data_t * const connector_ptr)
00461 {
00462     connector_status_t result;
00463     connector_buffer_t * packet_buffer;
00464 
00465     result = tcp_receive_packet(connector_ptr, &packet_buffer);
00466 
00467     if (result == connector_working)
00468     {
00469         uint8_t * edp_header;
00470 
00471         ASSERT(packet_buffer != NULL);
00472 
00473         edp_header = packet_buffer->buffer;
00474 
00475         /*
00476          * packet format:
00477          *  ----------------------------------------------
00478          * | 0 - 1 | 2 - 3 |        4         |  5 - 20   |
00479          *  ----------------------------------------------
00480          * |   EDP header  | Device ID opcode | Device ID |
00481          *  ----------------------------------------------
00482         */
00483         {
00484             uint8_t * const opcode = GET_PACKET_DATA_POINTER(edp_header, PACKET_EDP_HEADER_SIZE);
00485 
00486             if (*opcode != SECURITY_OPER_DEVICE_ID)
00487             {
00488                 /* Device ID error. Notify user. */
00489                 result = connector_abort;
00490             }
00491             else
00492             {
00493                 uint8_t * const device_id = opcode + sizeof(*opcode);
00494                 connector_request_id_t request_id;
00495                 connector_callback_status_t status;
00496                 connector_config_pointer_data_t device_id_data;
00497 
00498                 /* Update internal device_id, needed for future connections */
00499                 memcpy(connector_ptr->device_id, device_id, DEVICE_ID_LENGTH);
00500                 /* Call user function to save the provisioned Device ID */
00501                 device_id_data.bytes_required = DEVICE_ID_LENGTH;
00502                 device_id_data.data = device_id;
00503 
00504                 connector_debug_hexvalue("Received Device ID", device_id, DEVICE_ID_LENGTH);
00505 
00506                 request_id.config_request = connector_request_id_config_set_device_id;
00507                 status = connector_callback(connector_ptr->callback, connector_class_id_config, request_id, &device_id_data);
00508                 switch (status)
00509                 {
00510                 case connector_callback_continue:
00511                     break;
00512                 case connector_callback_abort:
00513                     result = connector_abort;
00514                     break;
00515                 case connector_callback_unrecognized:
00516                 case connector_callback_error:
00517                     result = connector_device_error;
00518                     break;
00519                 case connector_callback_busy:
00520                     result = connector_pending;
00521                     break;
00522                 }
00523             }
00524         }
00525 
00526         tcp_release_receive_packet(connector_ptr, packet_buffer);
00527     }
00528     else if (result == connector_idle) result = connector_pending;
00529 
00530     return result;
00531 }
00532 #endif
00533 
00534 static connector_status_t send_cloud_url(connector_data_t * const connector_ptr)
00535 {
00536     #define SECURITY_OPER_URL            UINT32_C(0x86)
00537 
00538     /*
00539      * packet format:
00540      *  ------------------------------------------------
00541      * | 0 - 1 | 2 - 3 |    4       |   5 - 6    | 7... |
00542      *  ------------------------------------------------
00543      * |   EDP Header  | URL opcode | URL length | URL  |
00544      *  ------------------------------------------------
00545     */
00546     enum edp_cloud_url {
00547         field_define(edp_cloud_url, opcode, uint8_t),
00548         field_define(edp_cloud_url, url_length, uint16_t),
00549         record_end(edp_cloud_url)
00550     };
00551     connector_status_t result;
00552     uint8_t * edp_header;
00553 
00554     char * cloud_url = connector_ptr->edp_data.config.cloud_url;
00555     uint8_t * edp_cloud_url;
00556     uint8_t * start_ptr;
00557 
00558     static char const url_prefix[] = URL_PREFIX;
00559     static size_t const prefix_length = sizeof url_prefix -1;
00560 
00561     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &start_ptr, NULL);
00562     if (edp_header == NULL)
00563     {
00564         result = connector_pending;
00565         goto done;
00566     }
00567 
00568     edp_cloud_url = start_ptr;
00569 
00570     connector_debug_printf("Send Device Cloud url = %.*s\n", (int)connector_ptr->edp_data.config.cloud_url_length, connector_ptr->edp_data.config.cloud_url);
00571 
00572     message_store_u8(edp_cloud_url, opcode, SECURITY_OPER_URL);
00573 
00574     {
00575         size_t const len = connector_ptr->edp_data.config.cloud_url_length + prefix_length;
00576         uint16_t const len16 = (uint16_t) len;
00577 
00578         ASSERT(len <= UINT16_MAX);
00579         message_store_be16(edp_cloud_url, url_length, len16);
00580     }
00581 
00582     edp_cloud_url += record_bytes(edp_cloud_url);
00583     memcpy(edp_cloud_url, url_prefix, prefix_length);
00584     edp_cloud_url += prefix_length;
00585 
00586     memcpy(edp_cloud_url, cloud_url, connector_ptr->edp_data.config.cloud_url_length);
00587     edp_cloud_url += connector_ptr->edp_data.config.cloud_url_length;
00588 
00589     {
00590         size_t const length = (size_t)(edp_cloud_url-start_ptr);
00591         ASSERT(edp_cloud_url > start_ptr);
00592 
00593         result = tcp_initiate_send_packet(connector_ptr, edp_header, length,
00594                                 E_MSG_MT2_TYPE_PAYLOAD,
00595                                 tcp_release_packet_buffer,
00596                                 NULL);
00597     }
00598 done:
00599     return result;
00600 }
00601 
00602 static connector_status_t send_password(connector_data_t * const connector_ptr)
00603 {
00604     #define SECURITY_OPER_PASSWORD            0x88
00605 
00606     /*
00607      * packet format:
00608      *  -----------------------------------------------------
00609      * | 0 - 1 | 2 - 3 |    4            |   5    | 7...     |
00610      *  -----------------------------------------------------
00611      * |   EDP Header  | password opcode | length | password |
00612      *  -----------------------------------------------------
00613     */
00614     enum edp_password {
00615         field_define(edp_password, opcode, uint8_t),
00616         field_define(edp_password, password_length, uint16_t),
00617         record_end(edp_password)
00618     };
00619     connector_status_t result;
00620     uint8_t * edp_header;
00621 
00622     uint8_t * edp_password;
00623     uint8_t * start_ptr;
00624 
00625     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &start_ptr, NULL);
00626     if (edp_header == NULL)
00627     {
00628         result = connector_pending;
00629         goto done;
00630     }
00631 
00632     edp_password = start_ptr;
00633 
00634     message_store_u8(edp_password, opcode, SECURITY_OPER_PASSWORD);
00635 
00636     {
00637         uint16_t const length16 = (uint16_t) connector_ptr->edp_data.config.password_length;
00638 
00639         ASSERT(connector_ptr->edp_data.config.password_length <= UINT16_MAX);
00640         message_store_be16(edp_password, password_length, length16);
00641     }
00642     edp_password += record_bytes(edp_password);
00643 
00644     memcpy(edp_password, connector_ptr->edp_data.config.password, connector_ptr->edp_data.config.password_length);
00645     edp_password += connector_ptr->edp_data.config.password_length;
00646 
00647     {
00648         size_t const length = (size_t)(edp_password-start_ptr);
00649 
00650         ASSERT(edp_password > start_ptr);
00651         result = tcp_initiate_send_packet(connector_ptr, edp_header, length,
00652                                 E_MSG_MT2_TYPE_PAYLOAD,
00653                                 tcp_release_packet_buffer,
00654                                 NULL);
00655     }
00656 done:
00657     return result;
00658 }
00659 
00660 static connector_status_t send_vendor_id(connector_data_t * const connector_ptr)
00661 {
00662     /*
00663      * packet format:
00664      *  ----------------------------------------------------------------
00665      * | 0 - 1 | 2 - 3 |       4         |       5          |  6 - 9    |
00666      *  ----------------------------------------------------------------
00667      * |   EDP Header  | security coding | vendor ID opcode | vendor ID |
00668      *  ----------------------------------------------------------------
00669     */
00670     enum edp_vendor_msg {
00671         field_define(edp_vendor_msg, security_coding, uint8_t),
00672         field_define(edp_vendor_msg, opcode, uint8_t),
00673         field_define(edp_vendor_msg, vendor_id, uint32_t),
00674         record_end(edp_vendor_msg)
00675     };
00676 
00677     connector_status_t result;
00678     uint8_t * edp_header = NULL;
00679 
00680     size_t const discovery_vendor_header_size = record_bytes(edp_vendor_msg);
00681     uint8_t * edp_vendor_msg;
00682 
00683     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &edp_vendor_msg, NULL);
00684     if (edp_header == NULL)
00685     {
00686         result = connector_pending;
00687         goto done;
00688     }
00689 
00690     message_store_u8(edp_vendor_msg, security_coding, SECURITY_PROTO_NONE);
00691     message_store_u8(edp_vendor_msg, opcode, DISC_OP_VENDOR_ID);
00692 #if !(defined CONNECTOR_VENDOR_ID)
00693     message_store_be32(edp_vendor_msg, vendor_id, connector_ptr->edp_data.config.vendor_id);
00694 #if (defined CONNECTOR_DEBUG)
00695     connector_debug_printf("Send vendor id = 0x%08X\n", connector_ptr->edp_data.config.vendor_id);
00696 #endif
00697 
00698 #else
00699     {
00700         message_store_be32(edp_vendor_msg, vendor_id, CONNECTOR_VENDOR_ID);
00701         connector_debug_printf("Send vendor id = 0x%08X\n", CONNECTOR_VENDOR_ID);
00702     }
00703 #endif
00704 
00705     result = tcp_initiate_send_packet(connector_ptr, edp_header,
00706                                 discovery_vendor_header_size,
00707                                 E_MSG_MT2_TYPE_PAYLOAD,
00708                                 tcp_release_packet_buffer,
00709                                 NULL);
00710 done:
00711     return result;
00712 }
00713 
00714 static connector_status_t send_device_type(connector_data_t * const connector_ptr)
00715 {
00716     /*
00717      * packet format:
00718      *  --------------------------------------------------------------------
00719      * | 0 - 1 | 2 - 3 |    4     |     5       |    6 - 7    |    8...     |
00720      *  --------------------------------------------------------------------
00721      * |   EDP Header  | security | device type | Device type | Device type |
00722      * |               |  coding  |   opcode    |   length    |             |
00723      *  --------------------------------------------------------------------
00724     */
00725     enum edp_device_type_msg {
00726         field_define(edp_device_type, security_coding, uint8_t),
00727         field_define(edp_device_type, opcode, uint8_t),
00728         field_define(edp_device_type, length, uint16_t),
00729         record_end(edp_device_type)
00730     };
00731     size_t const device_type_header_size = record_bytes(edp_device_type);
00732 
00733     connector_status_t result;
00734     uint8_t * edp_header = NULL;
00735     uint8_t * edp_device_type;
00736 
00737 #if (defined CONNECTOR_DEVICE_TYPE)
00738     static const char connector_device_type[] = CONNECTOR_DEVICE_TYPE;
00739     size_t device_type_length  = sizeof connector_device_type-1;
00740 #else
00741     char * connector_device_type = connector_ptr->edp_data.config.device_type;
00742     size_t const device_type_length = connector_ptr->edp_data.config.device_type_length;
00743 #endif
00744 
00745     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &edp_device_type, NULL);
00746     if (edp_header == NULL)
00747     {
00748         result = connector_pending;
00749         goto done;
00750     }
00751 
00752     message_store_u8(edp_device_type, security_coding, SECURITY_PROTO_NONE);
00753     message_store_u8(edp_device_type, opcode, DISC_OP_DEVICETYPE);
00754 
00755     {
00756         uint16_t const length16 = (uint16_t) device_type_length;
00757 
00758         ASSERT(device_type_length <= UINT8_MAX); /* Despite the size is a 16-bit integer, the maximum allowed is 255 */
00759         message_store_be16(edp_device_type, length, length16);
00760     }
00761 
00762     edp_device_type += device_type_header_size;
00763     memcpy(edp_device_type, connector_device_type, device_type_length);
00764 
00765     connector_debug_printf("Send device type = %.*s\n", (int)device_type_length, connector_device_type);
00766 
00767     result = tcp_initiate_send_packet(connector_ptr, edp_header,
00768                                 (device_type_header_size + device_type_length),
00769                                 E_MSG_MT2_TYPE_PAYLOAD,
00770                                 tcp_release_packet_buffer,
00771                                 NULL);
00772 done:
00773     return result;
00774 }
00775 
00776 static connector_status_t send_complete(connector_data_t * const connector_ptr)
00777 {
00778     /*
00779      * packet format:
00780      *  -----------------------------------------
00781      * | 0 - 1 | 2 - 3 |   4    |      5         |
00782      *  -----------------------------------------
00783      * |   EDP Header  | coding | initialization |
00784      * |               | scheme |   done opcode  |
00785      *  -----------------------------------------
00786     */
00787     enum edp_discovery_complete {
00788         field_define(edp_discovery_complete, security_coding, uint8_t),
00789         field_define(edp_discovery_complete, opcode, uint8_t),
00790         record_end(edp_discovery_complete)
00791     };
00792     size_t const discovery_complete_message_size = record_bytes(edp_discovery_complete);
00793     uint8_t * edp_discovery_complete;
00794     connector_status_t result;
00795     uint8_t * edp_header = NULL;
00796 
00797     edp_header = tcp_get_packet_buffer(connector_ptr, E_MSG_MT2_MSG_NUM, &edp_discovery_complete, NULL);
00798     if (edp_header == NULL)
00799     {
00800         result = connector_pending;
00801         goto done;
00802     }
00803 
00804     connector_debug_printf("Send complete\n");
00805     message_store_u8(edp_discovery_complete, security_coding, SECURITY_PROTO_NONE);
00806     message_store_u8(edp_discovery_complete, opcode, DISC_OP_INITCOMPLETE);
00807 
00808     result = tcp_initiate_send_packet(connector_ptr, edp_header,
00809                                 discovery_complete_message_size,
00810                                 E_MSG_MT2_TYPE_PAYLOAD,
00811                                 tcp_release_packet_buffer,
00812                                 NULL);
00813 
00814 done:
00815     return result;
00816 }
00817 
00818 static connector_status_t layer_discovery_facility(connector_data_t * const connector_ptr);
00819 
00820 static connector_status_t edp_tcp_open_process(connector_data_t * const connector_ptr)
00821 {
00822     connector_status_t result = connector_idle;
00823 
00824     switch (edp_get_edp_state(connector_ptr))
00825     {
00826     case edp_communication_connect_to_cloud:
00827         result = connect_to_cloud(connector_ptr, connector_ptr->edp_data.config.cloud_url);
00828 
00829         switch(result)
00830         {
00831         case connector_working:
00832             edp_set_edp_state(connector_ptr, edp_communication_send_version);
00833             connector_ptr->edp_data.send_packet.packet_buffer.in_use = connector_false;
00834             connector_ptr->edp_data.receive_packet.packet_buffer.in_use = connector_false;
00835             connector_ptr->edp_data.receive_packet.packet_buffer.next = NULL;
00836             connector_ptr->edp_data.receive_packet.free_packet_buffer = &connector_ptr->edp_data.receive_packet.packet_buffer;
00837             break;
00838         case connector_unavailable:
00839             edp_set_active_state(connector_ptr, connector_transport_idle);
00840             connector_ptr->edp_data.stop.auto_connect = connector_false;
00841             break;
00842         case connector_open_error:
00843         {
00844             connector_ptr->edp_data.connect_at = 0;
00845             edp_set_active_state(connector_ptr, connector_transport_wait_for_reconnect);
00846 #if (defined CONNECTOR_NETWORK_TCP_START)
00847             if (CONNECTOR_NETWORK_TCP_START == connector_connect_manual)
00848 #else
00849             if (connector_ptr->edp_data.connect_type == connector_connect_manual)
00850 #endif
00851             {
00852                 /* Application must call initiate_action to Start Cloud Connector */
00853                 edp_set_active_state(connector_ptr, connector_transport_idle);
00854             }
00855             break;
00856         }
00857         case connector_success:
00858         case connector_init_error:
00859         case connector_invalid_data_size:
00860         case connector_invalid_data_range:
00861         case connector_invalid_data:
00862         case connector_keepalive_error:
00863         case connector_bad_version:
00864         case connector_device_terminated:
00865         case connector_service_busy:
00866         case connector_invalid_response:
00867         case connector_no_resource:
00868         case connector_idle:
00869         case connector_pending:
00870         case connector_active:
00871         case connector_abort:
00872         case connector_device_error:
00873         case connector_exceed_timeout:
00874         case connector_invalid_payload_packet:
00875             break;
00876         }
00877         break;
00878 
00879     case edp_communication_send_version:
00880     case edp_communication_send_keepalive:
00881     case edp_initialization_send_protocol_version:
00882     case edp_security_send_identity_verification:
00883     case edp_security_send_device_id:
00884     case edp_security_send_device_cloud_url:
00885     case edp_security_send_password:
00886     case edp_discovery_send_vendor_id:
00887     case edp_discovery_send_device_type:
00888     case edp_discovery_facility:
00889     case edp_discovery_send_complete:
00890     {
00891         connector_edp_state_t next_state = edp_get_edp_state(connector_ptr);
00892 
00893         switch (edp_get_edp_state(connector_ptr))
00894         {
00895         case edp_communication_send_version:
00896             connector_debug_printf("Send MT Version\n");
00897             result = send_version(connector_ptr, E_MSG_MT2_TYPE_VERSION, EDP_MT_VERSION);
00898             if (result == connector_working)
00899             {
00900                 next_state = edp_communication_receive_version_response;
00901             }
00902             break;
00903 
00904         case edp_communication_send_keepalive:
00905             result = send_keepalive(connector_ptr);
00906             if (result == connector_working)
00907             {
00908                 next_state =  edp_initialization_send_protocol_version;
00909             }
00910             break;
00911 
00912         case edp_initialization_send_protocol_version:
00913         {
00914             #define EDP_PROTOCOL_VERSION    0x120
00915 
00916             connector_debug_printf("Send protocol version\n");
00917             result = send_version(connector_ptr, E_MSG_MT2_TYPE_PAYLOAD, EDP_PROTOCOL_VERSION);
00918             if (result == connector_working)
00919             {
00920                 next_state =  edp_initialization_receive_protocol_version;
00921             }
00922             break;
00923         }
00924         case edp_security_send_identity_verification:
00925             result = send_identity_verification(connector_ptr);
00926             if (result == connector_working)
00927             {
00928                 next_state =  edp_security_send_device_id;
00929             }
00930             break;
00931         case edp_security_send_device_id:
00932 #if (CONNECTOR_VERSION >= 0x02010000)
00933             if (connector_ptr->connector_got_device_id)
00934             {
00935                 result = send_device_id(connector_ptr);
00936                 if (result == connector_working)
00937                 {
00938                     next_state = edp_security_send_device_cloud_url;
00939                 }
00940             }
00941             else
00942             {
00943                 result = send_provisioning(connector_ptr);
00944                 if (result == connector_working)
00945                 {
00946                     next_state = edp_security_receive_device_id;
00947                 }
00948             }
00949 #else
00950             result = send_device_id(connector_ptr);
00951             if (result == connector_working)
00952                 next_state = edp_security_send_device_cloud_url;
00953 #endif
00954             break;
00955         case edp_security_send_device_cloud_url:
00956             result = send_cloud_url(connector_ptr);
00957             if (result == connector_working)
00958             {
00959 #if (defined CONNECTOR_IDENTITY_VERIFICATION)
00960                 next_state = (CONNECTOR_IDENTITY_VERIFICATION == connector_identity_verification_password) ? edp_security_send_password : edp_discovery_send_vendor_id;
00961 #else
00962                 next_state = (connector_ptr->edp_data.config.identity_verification == connector_identity_verification_password) ? edp_security_send_password : edp_discovery_send_vendor_id;
00963 #endif
00964             }
00965             break;
00966 
00967         case edp_security_send_password:
00968             result = send_password(connector_ptr);
00969             if (result == connector_working)
00970             {
00971                 next_state =  edp_discovery_send_vendor_id;
00972             }
00973             break;
00974 
00975         case edp_discovery_send_vendor_id:
00976             result = send_vendor_id(connector_ptr);
00977             if (result == connector_working)
00978             {
00979                 next_state =  edp_discovery_send_device_type;
00980             }
00981             break;
00982 
00983         case edp_discovery_send_device_type:
00984             result = send_device_type(connector_ptr);
00985             if (result == connector_working)
00986             {
00987                 next_state =  edp_discovery_facility;
00988             }
00989             break;
00990         case edp_discovery_facility:
00991             result = layer_discovery_facility(connector_ptr);
00992 
00993             if (result == connector_working)
00994             {
00995                 next_state = edp_discovery_send_complete;
00996             }
00997             break;
00998 
00999         case edp_discovery_send_complete:
01000             result = send_complete(connector_ptr);
01001             break;
01002 
01003         default:
01004             break;
01005         }
01006 
01007         if (result == connector_working || result == connector_idle || result == connector_pending)
01008         {
01009             result = edp_tcp_send_process(connector_ptr);
01010             if (result == connector_working)
01011             {
01012                 if (edp_get_edp_state(connector_ptr) == edp_discovery_send_complete)
01013                 {
01014                     /* we are connected and EDP communication is fully established. */
01015                     edp_set_edp_state(connector_ptr, edp_facility_process);
01016                     edp_set_active_state(connector_ptr, connector_transport_receive);
01017 
01018                     if (notify_status(connector_ptr->callback, connector_tcp_communication_started) != connector_working)
01019                         result = connector_abort;
01020 
01021                }
01022 
01023                 edp_set_edp_state(connector_ptr, next_state);
01024             }
01025         }
01026 
01027         goto done;
01028     }
01029     case edp_communication_receive_version_response:
01030         result = receive_edp_version(connector_ptr);
01031         if (result == connector_working)
01032         {
01033             edp_set_edp_state(connector_ptr, edp_communication_send_keepalive);
01034         }
01035 
01036         break;
01037 
01038     case edp_initialization_receive_protocol_version:
01039         result = receive_protocol_version(connector_ptr);
01040         if (result == connector_working)
01041         {
01042             edp_set_edp_state(connector_ptr, edp_security_send_identity_verification);
01043         }
01044         break;
01045 #if (CONNECTOR_VERSION >= 0x02010000)
01046     case edp_security_receive_device_id:
01047         result = receive_device_id(connector_ptr);
01048         if (result == connector_working)
01049         {
01050             connector_ptr->connector_got_device_id = connector_true;
01051             edp_set_edp_state(connector_ptr, edp_security_send_device_cloud_url);
01052         }
01053         break;
01054 #endif
01055     case edp_facility_process:
01056         /* Should not be here since active state should not be open state. */
01057         ASSERT(connector_false);
01058         break;
01059     }
01060 
01061 done:
01062     if (result != connector_idle && result != connector_pending && result != connector_working)
01063     {
01064         if (edp_get_edp_state(connector_ptr) != edp_communication_connect_to_cloud)
01065         {
01066            /* set the close state and make it goes to close connection state */
01067             edp_set_close_status(connector_ptr, connector_close_status_device_error);
01068             edp_set_active_state(connector_ptr, connector_transport_close);
01069             result = connector_working;
01070         }
01071     }
01072     return result;
01073 }
01074