Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-cloud-workshop-connect-HTS221 by
ftcd_comm_socket.cpp
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // http://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 // ---------------------------------------------------------------------------- 00016 00017 // Note: this macro is needed on armcc to get the the PRI*32 macros 00018 // from inttypes.h in a C++ code. 00019 #ifndef __STDC_FORMAT_MACROS 00020 #define __STDC_FORMAT_MACROS 00021 #endif 00022 00023 #include <stdlib.h> 00024 #include "pal.h" 00025 #include "pv_log.h" 00026 #include "ftcd_comm_socket.h" 00027 #include "fcc_malloc.h" 00028 00029 #define NUM_OF_PENDING_CONNECTIONS 1 00030 #define NUM_OF_TRIES_TO_GET_INTERFACE_INFO 5 00031 #define TRACE_GROUP "fcsk" 00032 #define RANDOM_PORT_MIN 1024 00033 #define RANDOM_PORT_MAX 65535 00034 00035 FtcdCommSocket::FtcdCommSocket(const void *interfaceHandler, ftcd_socket_domain_e domain, const uint16_t port_num, ftcd_comm_network_endianness_e network_endianness, int32_t timeout) 00036 : FtcdCommBase(network_endianness, NULL, false) 00037 { 00038 _interface_handler = interfaceHandler; 00039 _required_domain_type = domain; 00040 _port = port_num; 00041 _rcv_timeout = timeout; 00042 _current_domain_type = FTCD_AF_UNSPEC; 00043 _interface_index = 0; 00044 _net_interface_info = NULL; 00045 _server_socket = NULL; 00046 _client_socket = NULL; 00047 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00048 } 00049 00050 FtcdCommSocket::FtcdCommSocket(const void *interfaceHandler, ftcd_socket_domain_e domain, const uint16_t port_num, ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature, int32_t timeout) 00051 : FtcdCommBase(network_endianness, header_token, use_signature) 00052 00053 { 00054 _interface_handler = interfaceHandler; 00055 _required_domain_type = domain; 00056 _port = port_num; 00057 _rcv_timeout = timeout; 00058 _current_domain_type = FTCD_AF_UNSPEC; 00059 _interface_index = 0; 00060 _net_interface_info = NULL; 00061 _server_socket = NULL; 00062 _client_socket = NULL; 00063 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00064 } 00065 00066 FtcdCommSocket::~FtcdCommSocket() 00067 { 00068 00069 if (_net_interface_info != NULL) { 00070 fcc_free(_net_interface_info); 00071 } 00072 if (_server_socket != NULL) { 00073 pal_close(&_server_socket); 00074 } 00075 if (_client_socket != NULL) { 00076 pal_close(&_client_socket); 00077 } 00078 } 00079 00080 00081 bool FtcdCommSocket::init() 00082 { 00083 int retries = NUM_OF_TRIES_TO_GET_INTERFACE_INFO; 00084 palIpV4Addr_t ip_v4_addr; 00085 char ip_and_port_string[32] = { 0 }; 00086 uint32_t index = 0; 00087 00088 //Call to pal init 00089 palStatus_t result = pal_init(); 00090 if (result != PAL_SUCCESS) { 00091 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Error initializing pal"); 00092 return false; 00093 } 00094 00095 // If port is 0, generate random port 00096 // Pal currently does not support binding with port 0. 00097 if (_port == 0) { 00098 srand((unsigned int)pal_osKernelSysTick()); 00099 // Generate random port int the range [RANDOM_PORT_MIN, RANDOM_PORT_MAX - 1] including. 00100 _port = (uint16_t)(rand() % (RANDOM_PORT_MAX - RANDOM_PORT_MIN) + RANDOM_PORT_MIN); 00101 } 00102 00103 //Register connected interface handler 00104 result = pal_registerNetworkInterface((void*)_interface_handler, &_interface_index); 00105 if (result != 0) { 00106 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n pal_RegisterNetworkInterface Failed"); 00107 return false; 00108 } 00109 00110 //Allocate memory for interface info 00111 if (_net_interface_info == NULL) { 00112 _net_interface_info = (palNetInterfaceInfo_t *)fcc_malloc(sizeof(palNetInterfaceInfo_t )); 00113 if (_net_interface_info == NULL) { 00114 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Failed to allocate memory for network interface"); 00115 return false; 00116 } 00117 } 00118 00119 //Try to get interface info 00120 while (retries--) { 00121 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Trying receive interface ..."); 00122 result = pal_getNetInterfaceInfo(_interface_index, _net_interface_info); 00123 if (result != 0) { 00124 pal_osDelay(200); 00125 } else {//In case we have interface info we print it 00126 if (_required_domain_type != FTCD_IPV4) { 00127 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Illegal domain type"); 00128 break; 00129 } 00130 //Update domain type 00131 _current_domain_type = _required_domain_type; 00132 00133 result = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ip_v4_addr); 00134 if (result != PAL_SUCCESS) { 00135 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n palGetSockAddrIPV4Addr failed"); 00136 break; 00137 } 00138 memset(ip_and_port_string, 0, sizeof(ip_and_port_string)); 00139 index = 0; 00140 for (uint32_t i = 0; i < sizeof(palIpV4Addr_t); i++) { 00141 if (i < sizeof(palIpV4Addr_t) - 1) { 00142 index += sprintf(&ip_and_port_string[index], "%d.", ip_v4_addr[i]); 00143 } else { 00144 index += sprintf(&ip_and_port_string[index], "%d:", ip_v4_addr[i]); 00145 index += sprintf(&ip_and_port_string[index], "%d\n", _port); 00146 } 00147 } 00148 00149 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Factory Client IP Address and Port : %s", ip_and_port_string); 00150 //open and listen to socket 00151 if (_listen()) { 00152 return true; 00153 } else { 00154 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to listen to socket"); 00155 } 00156 00157 } 00158 00159 } 00160 00161 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n FCC did not succeed receive network interface !!!!!!"); 00162 //If we couldn't get interface info free allocated memory 00163 fcc_free(_net_interface_info); 00164 _net_interface_info = NULL; 00165 return false; 00166 00167 } 00168 00169 void FtcdCommSocket::finish(void) 00170 { 00171 if (_server_socket != NULL) { 00172 pal_close(&_server_socket); 00173 _server_socket = NULL; 00174 } 00175 if (_client_socket != NULL) { 00176 pal_close(&_client_socket); 00177 _client_socket = NULL; 00178 } 00179 pal_destroy(); 00180 } 00181 00182 // no_open_connection, connection_open, connection_open_timeout 00183 ftcd_comm_status_e FtcdCommSocket::wait_for_message(uint8_t **message_out, uint32_t *message_size_out) 00184 { 00185 int result = PAL_SUCCESS; 00186 ftcd_comm_status_e comm_status = FTCD_COMM_STATUS_SUCCESS; 00187 palSocketLength_t addrlen = sizeof(palSocketAddress_t); 00188 palSocketAddress_t address = { 0 }; 00189 bool reiterate; 00190 00191 do { 00192 reiterate = false; 00193 00194 if (_connection_state == SOCKET_WAIT_FOR_CONNECTION) { 00195 // wait to accept connection 00196 result = pal_accept(_server_socket, &address, &addrlen, &_client_socket); 00197 if (result == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00198 // Timeout 00199 return FTCD_COMM_NETWORK_TIMEOUT; 00200 } else if (result != PAL_SUCCESS) { 00201 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00202 } 00203 00204 } 00205 00206 // Set state as accepted connection 00207 _connection_state = SOCKET_CONNECTION_ACCEPTED; 00208 00209 // Read the message from an open connection, 00210 // if the connection has been closed by the client wait for a new connection 00211 comm_status = FtcdCommBase::wait_for_message(message_out, message_size_out); 00212 if (comm_status == FTCD_COMM_NETWORK_CONNECTION_CLOSED) { 00213 reiterate = true; // Set the reiterate flag so that we will wait for a new connection before returning from function 00214 } 00215 if (comm_status != FTCD_COMM_STATUS_SUCCESS) { // If error reading - close the client socket and back to SOCKET_CLOSED state 00216 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00217 } 00218 00219 } while (reiterate); 00220 return comm_status; 00221 } 00222 00223 ftcd_comm_status_e FtcdCommSocket::is_token_detected() 00224 { 00225 char c; 00226 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00227 size_t idx = 0; 00228 00229 //read char by char to detect token 00230 while (idx < FTCD_MSG_HEADER_TOKEN_SIZE_BYTES) { 00231 result = _read_from_socket(reinterpret_cast<void*>(&c), 1); 00232 00233 if (result != FTCD_COMM_STATUS_SUCCESS) { 00234 return result; 00235 } 00236 00237 if (c == _header_token[idx]) { 00238 idx++; 00239 } else { 00240 idx = 0; 00241 } 00242 } 00243 return result; 00244 } 00245 00246 00247 uint32_t FtcdCommSocket::read_message_size(void) 00248 { 00249 uint32_t message_size = 0; 00250 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00251 00252 result = _read_from_socket(reinterpret_cast<void*>(&message_size), sizeof(message_size)); 00253 if (result != FTCD_COMM_STATUS_SUCCESS) { 00254 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message size"); 00255 return 0; 00256 } 00257 00258 return message_size; 00259 } 00260 00261 bool FtcdCommSocket::read_message(uint8_t *message_out, size_t message_size) 00262 { 00263 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00264 00265 if (message_out == NULL) { 00266 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid message buffer"); 00267 return false; 00268 } 00269 00270 // Read CBOR message bytes 00271 // We assume that message_size is NOT bigger than INT_MAX 00272 result = _read_from_socket(reinterpret_cast<void*>(message_out), (int)message_size); 00273 if (result != FTCD_COMM_STATUS_SUCCESS) { 00274 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message bytes"); 00275 return false; 00276 } 00277 return true; 00278 } 00279 00280 00281 bool FtcdCommSocket::read_message_signature(uint8_t *sig, size_t sig_size) 00282 { 00283 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00284 00285 if (sig == NULL) { 00286 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid sig buffer"); 00287 return false; 00288 } 00289 00290 // Read signature from medium 00291 // We assume that sig_size is NOT bigger than INT_MAX 00292 result = _read_from_socket(reinterpret_cast<void*>(sig), (int)sig_size); 00293 if (result != FTCD_COMM_STATUS_SUCCESS) { 00294 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message signature bytes"); 00295 return false; 00296 } 00297 return true; 00298 } 00299 00300 00301 bool FtcdCommSocket::send(const uint8_t *data, uint32_t data_size) 00302 { 00303 bool success = true; 00304 palStatus_t result = PAL_SUCCESS; 00305 size_t sent_bytes = 0; 00306 size_t remaind_bytes = (size_t)data_size; 00307 00308 do { 00309 if (_connection_state != SOCKET_CONNECTION_ACCEPTED) { 00310 return FTCD_COMM_NETWORK_CONNECTION_CLOSED; 00311 } 00312 result = pal_send(_client_socket, data, remaind_bytes, &sent_bytes); 00313 if (result != PAL_SUCCESS) { 00314 // Drop current client for all errors 00315 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00316 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed pal_send"); 00317 success = false; 00318 break; 00319 } 00320 00321 if (sent_bytes == 0 || sent_bytes > remaind_bytes) { 00322 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Sending response message failed"); 00323 success = false; 00324 break; 00325 } 00326 remaind_bytes = remaind_bytes - sent_bytes; 00327 data += sent_bytes; 00328 00329 } while (remaind_bytes != 0); 00330 00331 return success; 00332 } 00333 00334 bool FtcdCommSocket::_listen(void) 00335 { 00336 int status; 00337 palStatus_t result = PAL_SUCCESS; 00338 palSocketAddress_t address = { 0 }; 00339 palIpV4Addr_t ipv4 = { 0 }; 00340 int enable_reuseaddr = 1; 00341 00342 //Check port number and domain type 00343 if (_port == 0) { 00344 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong port number"); 00345 return false; 00346 } 00347 00348 if (_current_domain_type != FTCD_IPV4) { 00349 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong domain type"); 00350 return false; 00351 } 00352 00353 //Open server and client sockets 00354 result = pal_socket((palSocketDomain_t )_current_domain_type, PAL_SOCK_STREAM_SERVER , false, _interface_index, &_server_socket); 00355 if (result != PAL_SUCCESS) { 00356 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed"); 00357 return false; 00358 } 00359 00360 result = pal_socket((palSocketDomain_t )_current_domain_type, PAL_SOCK_STREAM, false, _interface_index, &_client_socket); 00361 if (result != PAL_SUCCESS) { 00362 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed"); 00363 return false; 00364 } 00365 // reset connection state 00366 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00367 00368 status = pal_setSocketOptions(_server_socket, PAL_SO_REUSEADDR, &enable_reuseaddr, sizeof(enable_reuseaddr)); 00369 if (status != 0) { 00370 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to set SO_REUSEADDR (status %d)", status); 00371 return false; 00372 } 00373 00374 //Get ipv4 format address from interface info structure 00375 status = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ipv4); 00376 if (status != 0) { 00377 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot palGetSockAddrIPV4Addr (status %d)", status); 00378 return false; 00379 } 00380 00381 //Set the retrieved address to pal socket address 00382 status = pal_setSockAddrIPV4Addr(&address, ipv4); 00383 if (status != 0) { 00384 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket ipv4 address (status %d)", status); 00385 return false; 00386 } 00387 00388 //Set current port number to pal socket address 00389 status = pal_setSockAddrPort(&address, _port); 00390 if (status != 0) { 00391 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket port address (status %d)", status); 00392 return false; 00393 } 00394 00395 //set server socket timeout 00396 if (_rcv_timeout >= 0) { 00397 status = pal_setSocketOptions(_server_socket, PAL_SO_RCVTIMEO , &_rcv_timeout, sizeof(_rcv_timeout)); 00398 if (status != 0) { 00399 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set server socket timeout (status %d)", status); 00400 return false; 00401 } 00402 } 00403 00404 status = pal_bind(_server_socket, &address, _net_interface_info->addressSize); 00405 if (status != 0) { 00406 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_bind failed (status %d)", status); 00407 return false; 00408 } 00409 00410 status = pal_listen(_server_socket, NUM_OF_PENDING_CONNECTIONS); 00411 if (status != 0) { 00412 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_listen failed (status %d)", status); 00413 return false; 00414 } 00415 00416 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Factory Client is waiting for incoming connection..."); 00417 00418 return true; 00419 } 00420 00421 00422 ftcd_comm_status_e FtcdCommSocket::_read_from_socket(void * data_out, int data_out_size) 00423 { 00424 palStatus_t pal_status = PAL_SUCCESS; 00425 size_t bytes_received = 0; 00426 size_t left_to_read = data_out_size; 00427 uint8_t* buffer = (uint8_t*)data_out; 00428 while (left_to_read > 0) { 00429 if (_connection_state != SOCKET_CONNECTION_ACCEPTED) { 00430 return FTCD_COMM_NETWORK_CONNECTION_CLOSED; 00431 } 00432 bytes_received = 0; 00433 pal_status = pal_recv(_client_socket, buffer, left_to_read, &bytes_received); 00434 if (pal_status == PAL_ERR_SOCKET_CONNECTION_CLOSED ) { 00435 // Drop current client 00436 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00437 return FTCD_COMM_NETWORK_CONNECTION_CLOSED; 00438 } 00439 else if (pal_status == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00440 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket timeout"); 00441 return FTCD_COMM_NETWORK_TIMEOUT; 00442 } else if (pal_status != PAL_SUCCESS) { 00443 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket error, (status = 0x%" PRIx32 ")", (uint32_t)pal_status); 00444 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00445 } 00446 buffer += bytes_received; 00447 if (left_to_read < bytes_received) { 00448 return FTCD_COMM_INTERNAL_ERROR; 00449 } 00450 left_to_read -= bytes_received; 00451 } 00452 00453 return FTCD_COMM_STATUS_SUCCESS; 00454 } 00455 00456
Generated on Tue Jul 12 2022 19:12:12 by
1.7.2
