Toyomasa Watarai
/
Mbed-example-WS-W27
Mbed Cloud example program for workshop in W27 2018.
Embed:
(wiki syntax)
Show/hide line numbers
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 *interface_handler, ftcd_socket_domain_e domain, const uint16_t port_num, int32_t timeout) 00036 { 00037 _interface_handler = interface_handler; 00038 _required_domain_type = domain; 00039 00040 /* If port supplied is 0, generate random port similar to UNIX convention. 00041 * Pal currently does not support binding with port 0. 00042 */ 00043 _port = port_num; 00044 if (port_num == 0) { 00045 srand(pal_osKernelSysTick()); 00046 00047 // Generate random port int the range [RANDOM_PORT_MIN, RANDOM_PORT_MAX - 1] including. 00048 _port = (rand() % (RANDOM_PORT_MAX - RANDOM_PORT_MIN)) + RANDOM_PORT_MIN; 00049 } 00050 00051 _rcv_timeout = timeout; 00052 _current_domain_type = FTCD_AF_UNSPEC; 00053 _interface_index = 0; 00054 _net_interface_info = NULL; 00055 _server_socket = NULL; 00056 _client_socket = NULL; 00057 } 00058 00059 FtcdCommSocket::~FtcdCommSocket() 00060 { 00061 00062 if (_net_interface_info != NULL) { 00063 fcc_free(_net_interface_info); 00064 } 00065 if (_server_socket != NULL) { 00066 pal_close(&_server_socket); 00067 } 00068 if (_client_socket != NULL) { 00069 pal_close(&_client_socket); 00070 } 00071 } 00072 00073 00074 bool FtcdCommSocket::init() 00075 { 00076 00077 int retries = NUM_OF_TRIES_TO_GET_INTERFACE_INFO; 00078 palIpV4Addr_t ip_v4_addr; 00079 char ip_and_port_string[32] = { 0 }; 00080 uint32_t index = 0; 00081 00082 //Call to pal init 00083 palStatus_t result = pal_init(); 00084 if (result != PAL_SUCCESS) { 00085 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Error initializing pal"); 00086 return false; 00087 } 00088 00089 //Register connected interface handler 00090 result = pal_registerNetworkInterface((void*)_interface_handler, &_interface_index); 00091 if (result != 0) { 00092 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n pal_RegisterNetworkInterface Failed"); 00093 return false; 00094 } 00095 00096 //Allocate memory for interface info 00097 if (_net_interface_info == NULL) { 00098 _net_interface_info = (palNetInterfaceInfo_t *)fcc_malloc(sizeof(palNetInterfaceInfo_t )); 00099 if (_net_interface_info == NULL) { 00100 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Failed to allocate memory for network interface"); 00101 return false; 00102 } 00103 } 00104 00105 //Try to get interface info 00106 while (retries--) { 00107 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Trying receive interface ..."); 00108 result = pal_getNetInterfaceInfo(_interface_index, _net_interface_info); 00109 if (result != 0) { 00110 pal_osDelay(200); 00111 } else {//In case we have interface info we print it 00112 if (_required_domain_type != FTCD_IPV4) { 00113 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Illegal domain type"); 00114 break; 00115 } 00116 //Update domain type 00117 _current_domain_type = _required_domain_type; 00118 00119 result = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ip_v4_addr); 00120 if (result != PAL_SUCCESS) { 00121 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n palGetSockAddrIPV4Addr failed"); 00122 break; 00123 } 00124 memset(ip_and_port_string, 0, sizeof(ip_and_port_string)); 00125 index = 0; 00126 for (uint32_t i = 0; i < sizeof(palIpV4Addr_t); i++) { 00127 if (i < sizeof(palIpV4Addr_t) - 1) { 00128 index += sprintf(&ip_and_port_string[index], "%d.", ip_v4_addr[i]); 00129 } else { 00130 index += sprintf(&ip_and_port_string[index], "%d:", ip_v4_addr[i]); 00131 index += sprintf(&ip_and_port_string[index], "%d\n", _port); 00132 } 00133 } 00134 00135 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Factory Client IP Address and Port : %s", ip_and_port_string); 00136 //open and listen to socket 00137 if (_listen()) { 00138 return true; 00139 } else { 00140 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to listen to socket"); 00141 } 00142 00143 } 00144 00145 } 00146 00147 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n FCC did not succeed receive network interface !!!!!!"); 00148 //If we couldn't get interface info free allocated memory 00149 fcc_free(_net_interface_info); 00150 _net_interface_info = NULL; 00151 return false; 00152 00153 } 00154 00155 00156 void FtcdCommSocket::finish(void) 00157 { 00158 if (_server_socket != NULL) { 00159 pal_close(&_server_socket); 00160 _server_socket = NULL; 00161 } 00162 if (_client_socket != NULL) { 00163 pal_close(&_client_socket); 00164 _client_socket = NULL; 00165 } 00166 pal_destroy(); 00167 } 00168 00169 ftcd_comm_status_e FtcdCommSocket::is_token_detected(void) 00170 { 00171 char expected_token[] = FTCD_MSG_HEADER_TOKEN; 00172 char c; 00173 int result = PAL_SUCCESS; 00174 size_t idx = 0; 00175 palSocketLength_t addrlen = 0; 00176 palSocketAddress_t address = { 0 }; 00177 00178 result = pal_accept(_server_socket, &address, &addrlen, &_client_socket); 00179 if (result == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00180 return FTCD_COMM_NETWORK_TIMEOUT; 00181 } else if (result != PAL_SUCCESS) { 00182 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00183 } 00184 00185 //read char by char to detect token 00186 while (idx < FTCD_MSG_HEADER_TOKEN_SIZE_BYTES) { 00187 result = _read_from_socket(reinterpret_cast<void*>(&c), 1); 00188 if (result == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00189 return FTCD_COMM_NETWORK_TIMEOUT; 00190 } else if (result != PAL_SUCCESS) { 00191 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00192 } 00193 00194 if (c == expected_token[idx]) { 00195 idx++; 00196 } else { 00197 idx = 0; 00198 } 00199 } 00200 return FTCD_COMM_STATUS_SUCCESS; 00201 } 00202 00203 00204 uint32_t FtcdCommSocket::read_message_size(void) 00205 { 00206 uint32_t message_size = 0; 00207 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00208 00209 result = _read_from_socket(reinterpret_cast<void*>(&message_size), sizeof(message_size)); 00210 if (result != FTCD_COMM_STATUS_SUCCESS) { 00211 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message size\r"); 00212 return 0; 00213 } 00214 00215 return message_size; 00216 } 00217 00218 bool FtcdCommSocket::read_message(uint8_t *message_out, size_t message_size) 00219 { 00220 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00221 00222 if (message_out == NULL) { 00223 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid message buffer\r"); 00224 return false; 00225 } 00226 00227 // Read CBOR message bytes 00228 // We assume that LENGTH is NOT bigger than INT_MAX 00229 result = _read_from_socket(reinterpret_cast<void*>(message_out), message_size); 00230 if (result != FTCD_COMM_STATUS_SUCCESS) { 00231 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message bytes\r"); 00232 return false; 00233 } 00234 return true; 00235 } 00236 00237 00238 bool FtcdCommSocket::read_message_signature(uint8_t *sig, size_t sig_size) 00239 { 00240 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00241 00242 if (sig == NULL) { 00243 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid sig buffer\r"); 00244 return false; 00245 } 00246 00247 // Read signature from medium 00248 result = _read_from_socket(reinterpret_cast<void*>(sig), sig_size); 00249 if (result != FTCD_COMM_STATUS_SUCCESS) { 00250 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message signature bytes\r"); 00251 return false; 00252 } 00253 return true; 00254 } 00255 00256 00257 bool FtcdCommSocket::send(const uint8_t *data, uint32_t data_size) 00258 { 00259 bool success = true; 00260 palStatus_t result = PAL_SUCCESS; 00261 size_t sent_bytes = 0; 00262 size_t remaind_bytes = (size_t)data_size; 00263 00264 do { 00265 result = pal_send(_client_socket, data, remaind_bytes, &sent_bytes); 00266 if (result != PAL_SUCCESS) { 00267 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed pal_send\r"); 00268 success = false; 00269 break; 00270 } 00271 00272 if (sent_bytes == 0 || sent_bytes > remaind_bytes) { 00273 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Sending response message failed"); 00274 success = false; 00275 break; 00276 } 00277 remaind_bytes = remaind_bytes - sent_bytes; 00278 data += sent_bytes; 00279 00280 } while (remaind_bytes != 0); 00281 00282 return success; 00283 } 00284 00285 bool FtcdCommSocket::_listen(void) 00286 { 00287 int status; 00288 palStatus_t result = PAL_SUCCESS; 00289 palSocketAddress_t address = { 0 }; 00290 palIpV4Addr_t ipv4 = { 0 }; 00291 00292 //Check port number and domain type 00293 if (_port == 0) { 00294 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong port number"); 00295 return false; 00296 } 00297 00298 if (_current_domain_type != FTCD_IPV4) { 00299 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong domain type"); 00300 return false; 00301 } 00302 00303 //Open server and client sockets 00304 result = pal_socket((palSocketDomain_t )_current_domain_type, PAL_SOCK_STREAM_SERVER , false, _interface_index, &_server_socket); 00305 if (result != PAL_SUCCESS) { 00306 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed"); 00307 return false; 00308 } 00309 00310 result = pal_socket((palSocketDomain_t )_current_domain_type, PAL_SOCK_STREAM, false, _interface_index, &_client_socket); 00311 if (result != PAL_SUCCESS) { 00312 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed"); 00313 return false; 00314 } 00315 00316 //Get ipv4 format address from interface info structure 00317 status = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ipv4); 00318 if (status != 0) { 00319 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot palGetSockAddrIPV4Addr (status %d)", status); 00320 return false; 00321 } 00322 00323 //Set the retrieved address to pal socket address 00324 status = pal_setSockAddrIPV4Addr(&address, ipv4); 00325 if (status != 0) { 00326 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket ipv4 address (status %d)", status); 00327 return false; 00328 } 00329 00330 //Set current port number to pal socket address 00331 status = pal_setSockAddrPort(&address, _port); 00332 if (status != 0) { 00333 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket port address (status %d)", status); 00334 return false; 00335 } 00336 00337 //set server socket timeout 00338 if (_rcv_timeout >= 0) { 00339 status = pal_setSocketOptions(_server_socket, PAL_SO_RCVTIMEO , &_rcv_timeout, sizeof(_rcv_timeout)); 00340 if (status != 0) { 00341 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set server socket timeout (status %d)", status); 00342 return false; 00343 } 00344 } 00345 00346 status = pal_bind(_server_socket, &address, _net_interface_info->addressSize); 00347 if (status != 0) { 00348 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_bind failed (status %d)", status); 00349 return false; 00350 } 00351 00352 status = pal_listen(_server_socket, NUM_OF_PENDING_CONNECTIONS); 00353 if (status != 0) { 00354 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_listen failed (status %d)", status); 00355 return false; 00356 } 00357 00358 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Factory Client is waiting for incoming connection..."); 00359 00360 return true; 00361 } 00362 00363 00364 ftcd_comm_status_e FtcdCommSocket::_read_from_socket(void * data_out, int data_out_size) 00365 { 00366 int status = PAL_SUCCESS; 00367 size_t bytes_received = 0; 00368 00369 if (data_out == NULL) { 00370 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid message"); 00371 return FTCD_COMM_INTERNAL_ERROR; 00372 } 00373 00374 status = pal_recv(_client_socket, data_out, data_out_size, &bytes_received); 00375 if (status == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00376 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket timeout, (status = %i)", status); 00377 return FTCD_COMM_NETWORK_TIMEOUT; 00378 } else if (status != PAL_SUCCESS) { 00379 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket error, (status = %i)", status); 00380 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00381 } 00382 00383 /* FIXME: The socket reads up to MSS (Max Segment Size) which is 1460 bytes. 00384 A bigger message would result in a partial message read. A temporary solution 00385 is to loop through until socket emptiness */ 00386 00387 // The number of bytes we had managed to read so far 00388 int bytes_read_successfully = bytes_received; 00389 00390 // The remaining bytes left to read 00391 int remaining_bytes = data_out_size - bytes_received; 00392 00393 // Loop through until nothing left to read 00394 while (remaining_bytes > 0) { 00395 00396 //Zero bytes_received before next receive 00397 bytes_received = 0; 00398 00399 status = pal_recv(_client_socket, (uint8_t *)data_out + bytes_read_successfully, remaining_bytes, &bytes_received); 00400 if (status == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00401 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket timeout, (status = %i)", status); 00402 return FTCD_COMM_NETWORK_TIMEOUT; 00403 } else if (status != PAL_SUCCESS) { 00404 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket error, (status = %i)", status); 00405 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00406 } 00407 00408 remaining_bytes -= bytes_received; 00409 bytes_read_successfully += bytes_received; 00410 } 00411 return FTCD_COMM_STATUS_SUCCESS; 00412 } 00413 00414
Generated on Tue Jul 12 2022 16:22:06 by 1.7.2