Simulated product dispenser
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