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.
Dependencies: FXAS21002 FXOS8700Q
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 #define FTCD_SEM_TIMEOUT ( (_rcv_timeout == INFINITE_SOCKET_TIMEOUT) ? (PAL_RTOS_WAIT_FOREVER) : (_rcv_timeout) ) 00036 00037 // Cabllback triggered by socket events 00038 // Non-blocking async sockets are used with blocking wrappers that wait on _async_sem. 00039 // This callback signals the waiting semaphore in the blocking wrappers 00040 00041 // We must be sure that we do not have a situations where sem is being waited and then 2 releases prior to the next wait: 00042 00043 00044 /* Scenario 1 (All according to plan) 00045 ************************************************************************************************************************************************************************************************************************************************************************************ 00046 Network thread/threads: ----------------------------------------------_socket_event_ready_cb -> take _lock -> signal (release) _aync_sem=1 ----------------------------------------------------------- _socket_event_ready_cb -> take _lock -> signal (release) _aync_sem=1 00047 00048 00049 00050 application thread: _wait_for_socket_event (on _async_sem=0) --------------------------------------------------------------------------_aync_sem=0------- release _lock ------------- _wait_for_socket_event --------------------------------------------------------------->>> 00051 ************************************************************************************************************************************************************************************************************************************************************************************ 00052 */ 00053 00054 /* Scenario 2 (Event signals _async_sem before release _lock in _wait_for_socket_event) 00055 ************************************************************************************************************************************************************************************************************************************************************************************ 00056 Network thread/threads: ----------------------------------------------_socket_event_ready_cb -> take _lock -> signal (release) _aync_sem=1 ---- _socket_event_ready_cb -> ----try to take _lock and fail (locked)------------------------------------------------------------------- 00057 00058 00059 00060 application thread: _wait_for_socket_event (on _async_sem=0) --------------------------------------------------------------------------_aync_sem=0--------------------------------------------------------- release _lock ------next action attempt and probably fail---- _wait_for_socket_event (block)-->>> 00061 ************************************************************************************************************************************************************************************************************************************************************************************ 00062 */ 00063 00064 /* Scenario 3 (Multiple events are invoked before _wait_for_socket_event() stops blocking) 00065 ************************************************************************************************************************************************************************************************************************************************************************************ 00066 Network thread/threads: ----------------------------------------------_socket_event_ready_cb -> take _lock -> signal (release) _aync_sem=1 ---- _socket_event_ready_cb -> try to take _lock and fail (locked) ------------------------------------ 00067 00068 00069 00070 application thread: _wait_for_socket_event (on _async_sem=0) ---------------------------------------------------------------------------------------------------------------------------------------_aync_sem=0--release _lock---------next action attempt and probably succeed (2nd event)-->>> 00071 ************************************************************************************************************************************************************************************************************************************************************************************ 00072 */ 00073 00074 00075 00076 void FtcdCommSocket::_socket_event_ready_cb(void *socket_obj) 00077 { 00078 palStatus_t pal_status; 00079 // No need for NULL check, we pass a valid pointer 00080 FtcdCommSocket *obj = static_cast<FtcdCommSocket *>(socket_obj); 00081 // Do not print log, may be called from ISR 00082 00083 // First lock - this prevents a scenario where sem count is greater then n (1 in our case) which is undefined behavior 00084 pal_status = pal_osSemaphoreWait(obj->_lock, 0, NULL); 00085 00086 // If lock is taken by another thread - do not signal _async_sem because its count is 1. 00087 // This scenario will happen if _socket_event_ready_cb() is triggered twice, before _lock is released in _wait_for_socket_event() 00088 // No need to signal _async_sem because it is already free 00089 // Note that our blocking wrappers first try to do the operation, and then block until an event occurs 00090 if (pal_status != PAL_SUCCESS) { 00091 return; 00092 } 00093 00094 // After we take the lock, we may signal sem 00095 (void)pal_osSemaphoreRelease(obj->_async_sem); 00096 } 00097 00098 palStatus_t FtcdCommSocket::_wait_for_socket_event() 00099 { 00100 palStatus_t pal_status; 00101 // Wait for signal from a new event, signaled by _socket_event_ready_cb() 00102 pal_status = pal_osSemaphoreWait(_async_sem, FTCD_SEM_TIMEOUT, NULL); 00103 00104 // Unlock the lock so that one more signal may be signaled from an event 00105 (void)pal_osSemaphoreRelease((palSemaphoreID_t)_lock); 00106 00107 return pal_status; 00108 } 00109 00110 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) 00111 : FtcdCommBase(network_endianness, NULL, false) 00112 { 00113 _interface_handler = interfaceHandler; 00114 _required_domain_type = domain; 00115 _port = port_num; 00116 _rcv_timeout = timeout; 00117 _current_domain_type = FTCD_AF_UNSPEC; 00118 _interface_index = 0; 00119 _net_interface_info = NULL; 00120 _server_socket = NULL; 00121 _client_socket = NULL; 00122 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00123 (void)pal_osSemaphoreCreate(1, &_async_sem); 00124 (void)pal_osSemaphoreCreate(1, &_lock); 00125 00126 } 00127 00128 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) 00129 : FtcdCommBase(network_endianness, header_token, use_signature) 00130 00131 { 00132 _interface_handler = interfaceHandler; 00133 _required_domain_type = domain; 00134 _port = port_num; 00135 _rcv_timeout = timeout; 00136 _current_domain_type = FTCD_AF_UNSPEC; 00137 _interface_index = 0; 00138 _net_interface_info = NULL; 00139 _server_socket = NULL; 00140 _client_socket = NULL; 00141 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00142 (void)pal_osSemaphoreCreate(1, &_async_sem); 00143 (void)pal_osSemaphoreCreate(1, &_lock); 00144 } 00145 00146 FtcdCommSocket::~FtcdCommSocket() 00147 { 00148 00149 if (_net_interface_info != NULL) { 00150 fcc_free(_net_interface_info); 00151 } 00152 if (_server_socket != NULL) { 00153 pal_close(&_server_socket); 00154 } 00155 if (_client_socket != NULL) { 00156 pal_close(&_client_socket); 00157 } 00158 } 00159 00160 00161 bool FtcdCommSocket::init() 00162 { 00163 int retries = NUM_OF_TRIES_TO_GET_INTERFACE_INFO; 00164 palIpV4Addr_t ip_v4_addr; 00165 char ip_and_port_string[32] = { 0 }; 00166 uint32_t index = 0; 00167 00168 //Call to pal init 00169 palStatus_t result = pal_init(); 00170 if (result != PAL_SUCCESS) { 00171 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Error initializing pal"); 00172 return false; 00173 } 00174 00175 // If port is 0, generate random port 00176 // Pal currently does not support binding with port 0. 00177 if (_port == 0) { 00178 srand((unsigned int)pal_osKernelSysTick()); 00179 // Generate random port int the range [RANDOM_PORT_MIN, RANDOM_PORT_MAX - 1] including. 00180 _port = (uint16_t)(rand() % (RANDOM_PORT_MAX - RANDOM_PORT_MIN) + RANDOM_PORT_MIN); 00181 } 00182 00183 //Register connected interface handler 00184 result = pal_registerNetworkInterface((void*)_interface_handler, &_interface_index); 00185 if (result != 0) { 00186 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n pal_RegisterNetworkInterface Failed"); 00187 return false; 00188 } 00189 00190 //Allocate memory for interface info 00191 if (_net_interface_info == NULL) { 00192 _net_interface_info = (palNetInterfaceInfo_t*)fcc_malloc(sizeof(palNetInterfaceInfo_t)); 00193 if (_net_interface_info == NULL) { 00194 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Failed to allocate memory for network interface"); 00195 return false; 00196 } 00197 } 00198 00199 //Try to get interface info 00200 while (retries--) { 00201 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Trying receive interface ..."); 00202 result = pal_getNetInterfaceInfo(_interface_index, _net_interface_info); 00203 if (result != 0) { 00204 pal_osDelay(200); 00205 } else {//In case we have interface info we print it 00206 if (_required_domain_type != FTCD_IPV4) { 00207 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Illegal domain type"); 00208 break; 00209 } 00210 //Update domain type 00211 _current_domain_type = _required_domain_type; 00212 00213 result = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ip_v4_addr); 00214 if (result != PAL_SUCCESS) { 00215 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n palGetSockAddrIPV4Addr failed"); 00216 break; 00217 } 00218 memset(ip_and_port_string, 0, sizeof(ip_and_port_string)); 00219 index = 0; 00220 for (uint32_t i = 0; i < sizeof(palIpV4Addr_t); i++) { 00221 if (i < sizeof(palIpV4Addr_t) - 1) { 00222 index += sprintf(&ip_and_port_string[index], "%d.", ip_v4_addr[i]); 00223 } else { 00224 index += sprintf(&ip_and_port_string[index], "%d:", ip_v4_addr[i]); 00225 index += sprintf(&ip_and_port_string[index], "%d\n", _port); 00226 } 00227 } 00228 00229 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Factory Client IP Address and Port : %s", ip_and_port_string); 00230 //open and listen to socket 00231 if (_listen()) { 00232 return true; 00233 } else { 00234 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to listen to socket"); 00235 } 00236 00237 } 00238 00239 } 00240 00241 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n FCC did not succeed receive network interface !!!!!!"); 00242 //If we couldn't get interface info free allocated memory 00243 fcc_free(_net_interface_info); 00244 _net_interface_info = NULL; 00245 return false; 00246 00247 } 00248 00249 void FtcdCommSocket::finish(void) 00250 { 00251 if (_server_socket != NULL) { 00252 pal_close(&_server_socket); 00253 _server_socket = NULL; 00254 } 00255 if (_client_socket != NULL) { 00256 pal_close(&_client_socket); 00257 _client_socket = NULL; 00258 } 00259 pal_destroy(); 00260 } 00261 00262 00263 /* 00264 There are 2 possible scenarios where _accept() is called: 00265 1. Very likely: sem=1 -> _listen(), sem=0 -> create socket -> _accept(), sem=0(block) -> _socket_event_ready_cb(), sem=1 -> accept() resumes, sem=0 -> nonblocking pal_accept() 00266 2. Very unlikely: sem=1 -> _listen(), sem=0 -> create socket -> _socket_event_ready_cb(), sem=1 -> _accept() never blocks, sem=0 -> nonblocking pal_accept() 00267 */ 00268 palStatus_t FtcdCommSocket::_accept(palSocket_t socket, palSocketAddress_t* address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket) 00269 { 00270 palStatus_t pal_status, result; 00271 00272 while (true) { 00273 pal_status = pal_accept(socket, address, addressLen, acceptedSocket); 00274 if (pal_status == PAL_ERR_SOCKET_WOULD_BLOCK ) { // Async socket has no connection to accept - wait on semaphore and try again 00275 pal_status = _wait_for_socket_event(); 00276 if (pal_status == PAL_ERR_RTOS_TIMEOUT ) { // Semaphore timeout means no event was triggered for _rcv_timeout ms so we return a WOULDBLOCK error according to blocking socket convention 00277 result = PAL_ERR_SOCKET_WOULD_BLOCK ; 00278 break; 00279 } else if (pal_status != PAL_SUCCESS){ // Should not happen - some unknown semaphore error 00280 result = pal_status; 00281 break; 00282 } 00283 // else: Semaphore signaled by event try accepting again 00284 00285 } else { // Either success, or error other than PAL_ERR_SOCKET_WOULD_BLOCK, return the status 00286 result = pal_status; 00287 break; 00288 } 00289 } 00290 00291 return result; 00292 } 00293 00294 // no_open_connection, connection_open, connection_open_timeout 00295 ftcd_comm_status_e FtcdCommSocket::wait_for_message(uint8_t **message_out, uint32_t *message_size_out) 00296 { 00297 int result = PAL_SUCCESS; 00298 ftcd_comm_status_e comm_status = FTCD_COMM_STATUS_SUCCESS; 00299 palSocketLength_t addrlen = sizeof(palSocketAddress_t); 00300 palSocketAddress_t address = { 0 , { 0 } }; 00301 bool reiterate; 00302 00303 do { 00304 reiterate = false; 00305 00306 if (_connection_state == SOCKET_WAIT_FOR_CONNECTION) { 00307 // wait to accept connection 00308 result = _accept(_server_socket, &address, &addrlen, &_client_socket); 00309 if (result == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00310 // Timeout 00311 return FTCD_COMM_NETWORK_TIMEOUT; 00312 } else if (result != PAL_SUCCESS) { 00313 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00314 } 00315 00316 } 00317 00318 // Set state as accepted connection 00319 _connection_state = SOCKET_CONNECTION_ACCEPTED; 00320 00321 // Read the message from an open connection, 00322 // if the connection has been closed by the client wait for a new connection 00323 comm_status = FtcdCommBase::wait_for_message(message_out, message_size_out); 00324 if (comm_status == FTCD_COMM_NETWORK_CONNECTION_CLOSED) { 00325 reiterate = true; // Set the reiterate flag so that we will wait for a new connection before returning from function 00326 } 00327 if (comm_status != FTCD_COMM_STATUS_SUCCESS) { // If error reading - close the client socket and back to SOCKET_CLOSED state 00328 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00329 } 00330 00331 } while (reiterate); 00332 return comm_status; 00333 } 00334 00335 ftcd_comm_status_e FtcdCommSocket::is_token_detected() 00336 { 00337 char c; 00338 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00339 size_t idx = 0; 00340 00341 //read char by char to detect token 00342 while (idx < FTCD_MSG_HEADER_TOKEN_SIZE_BYTES) { 00343 result = _read_from_socket(reinterpret_cast<void*>(&c), 1); 00344 00345 if (result != FTCD_COMM_STATUS_SUCCESS) { 00346 return result; 00347 } 00348 00349 if (c == _header_token[idx]) { 00350 idx++; 00351 } else { 00352 idx = 0; 00353 } 00354 } 00355 return result; 00356 } 00357 00358 00359 uint32_t FtcdCommSocket::read_message_size(void) 00360 { 00361 uint32_t message_size = 0; 00362 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00363 00364 result = _read_from_socket(reinterpret_cast<void*>(&message_size), sizeof(message_size)); 00365 if (result != FTCD_COMM_STATUS_SUCCESS) { 00366 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message size"); 00367 return 0; 00368 } 00369 00370 return message_size; 00371 } 00372 00373 bool FtcdCommSocket::read_message(uint8_t *message_out, size_t message_size) 00374 { 00375 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00376 00377 if (message_out == NULL) { 00378 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid message buffer"); 00379 return false; 00380 } 00381 00382 // Read CBOR message bytes 00383 // We assume that message_size is NOT bigger than INT_MAX 00384 result = _read_from_socket(reinterpret_cast<void*>(message_out), (int)message_size); 00385 if (result != FTCD_COMM_STATUS_SUCCESS) { 00386 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message bytes"); 00387 return false; 00388 } 00389 return true; 00390 } 00391 00392 00393 bool FtcdCommSocket::read_message_signature(uint8_t *sig, size_t sig_size) 00394 { 00395 ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS; 00396 00397 if (sig == NULL) { 00398 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid sig buffer"); 00399 return false; 00400 } 00401 00402 // Read signature from medium 00403 // We assume that sig_size is NOT bigger than INT_MAX 00404 result = _read_from_socket(reinterpret_cast<void*>(sig), (int)sig_size); 00405 if (result != FTCD_COMM_STATUS_SUCCESS) { 00406 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message signature bytes"); 00407 return false; 00408 } 00409 return true; 00410 } 00411 00412 #define MS_BETWEEN_SOCKET_SEND_RETRIES 500 00413 palStatus_t FtcdCommSocket::_send(palSocket_t socket, const void* buf, size_t len, size_t* sentDataSize) 00414 { 00415 palStatus_t result = PAL_SUCCESS; 00416 00417 // in blocking mode (linux socket) - pal_send will block until the buffer is copied into the kernel's networking stack buffer 00418 // In our case, non-blocking (linux socket) - will return a EWOULDBLOCK error if the kernel's buffer, so we will wait and retry (should work on first try) 00419 00420 while (true) { 00421 result = pal_send(socket, buf, len, sentDataSize); 00422 if (result == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00423 pal_osDelay(MS_BETWEEN_SOCKET_SEND_RETRIES); 00424 } else { // If any other error, or success - return the status 00425 break; 00426 } 00427 } 00428 00429 return result; 00430 } 00431 00432 bool FtcdCommSocket::send(const uint8_t *data, uint32_t data_size) 00433 { 00434 bool success = true; 00435 palStatus_t result = PAL_SUCCESS; 00436 size_t sent_bytes = 0; 00437 size_t remaind_bytes = (size_t)data_size; 00438 00439 do { 00440 if (_connection_state != SOCKET_CONNECTION_ACCEPTED) { 00441 return FTCD_COMM_NETWORK_CONNECTION_CLOSED; 00442 } 00443 result = _send(_client_socket, data, remaind_bytes, &sent_bytes); 00444 if (result != PAL_SUCCESS) { 00445 // Drop current client for all errors 00446 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00447 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed pal_send"); 00448 success = false; 00449 break; 00450 } 00451 00452 if (sent_bytes == 0 || sent_bytes > remaind_bytes) { 00453 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Sending response message failed"); 00454 success = false; 00455 break; 00456 } 00457 remaind_bytes = remaind_bytes - sent_bytes; 00458 data += sent_bytes; 00459 00460 } while (remaind_bytes != 0); 00461 00462 return success; 00463 } 00464 00465 bool FtcdCommSocket::_listen(void) 00466 { 00467 int status; 00468 palStatus_t result = PAL_SUCCESS; 00469 palSocketAddress_t address = { 0 , { 0 } }; 00470 palIpV4Addr_t ipv4 = { 0 }; 00471 int enable_reuseaddr = 1; 00472 00473 //Check port number and domain type 00474 if (_port == 0) { 00475 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong port number"); 00476 return false; 00477 } 00478 00479 if (_current_domain_type != FTCD_IPV4) { 00480 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong domain type"); 00481 return false; 00482 } 00483 00484 // Decrement sem count to 0 prior to socket creation. This assures that no socket async event may occur while sem=1 (the initial value) 00485 // Following call to pal_osSemaphoreWait will block 00486 result = pal_osSemaphoreWait(_async_sem, PAL_RTOS_WAIT_FOREVER, NULL); 00487 if (PAL_SUCCESS != result) { 00488 return false; 00489 } 00490 00491 //Open server and client sockets 00492 result = pal_asynchronousSocketWithArgument((palSocketDomain_t)_current_domain_type, PAL_SOCK_STREAM_SERVER, true, _interface_index, _socket_event_ready_cb, (void*)this, &_server_socket); 00493 if (result != PAL_SUCCESS) { 00494 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed"); 00495 return false; 00496 } 00497 00498 result = pal_asynchronousSocketWithArgument((palSocketDomain_t)_current_domain_type, PAL_SOCK_STREAM, true, _interface_index, _socket_event_ready_cb, (void*)this, &_client_socket); 00499 00500 if (result != PAL_SUCCESS) { 00501 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed"); 00502 return false; 00503 } 00504 // reset connection state 00505 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00506 00507 status = pal_setSocketOptions(_server_socket, PAL_SO_REUSEADDR, &enable_reuseaddr, sizeof(enable_reuseaddr)); 00508 if (status != 0) { 00509 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to set SO_REUSEADDR (status %d)", status); 00510 return false; 00511 } 00512 00513 //Get ipv4 format address from interface info structure 00514 status = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ipv4); 00515 if (status != 0) { 00516 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot palGetSockAddrIPV4Addr (status %d)", status); 00517 return false; 00518 } 00519 00520 //Set the retrieved address to pal socket address 00521 status = pal_setSockAddrIPV4Addr(&address, ipv4); 00522 if (status != 0) { 00523 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket ipv4 address (status %d)", status); 00524 return false; 00525 } 00526 00527 //Set current port number to pal socket address 00528 status = pal_setSockAddrPort(&address, _port); 00529 if (status != 0) { 00530 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket port address (status %d)", status); 00531 return false; 00532 } 00533 00534 //set server socket timeout 00535 if (_rcv_timeout >= 0) { 00536 status = pal_setSocketOptions(_server_socket, PAL_SO_RCVTIMEO, &_rcv_timeout, sizeof(_rcv_timeout)); 00537 if (status != 0) { 00538 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set server socket timeout (status %d)", status); 00539 return false; 00540 } 00541 } 00542 00543 status = pal_bind(_server_socket, &address, _net_interface_info->addressSize); 00544 if (status != 0) { 00545 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_bind failed (status %d)", status); 00546 return false; 00547 } 00548 00549 status = pal_listen(_server_socket, NUM_OF_PENDING_CONNECTIONS); 00550 if (status != 0) { 00551 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_listen failed (status %d)", status); 00552 return false; 00553 } 00554 00555 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Factory Client is waiting for incoming connection..."); 00556 00557 return true; 00558 } 00559 00560 palStatus_t FtcdCommSocket::_recv(palSocket_t socket, void* buf, size_t len, size_t* recievedDataSize) 00561 { 00562 palStatus_t pal_status, result; 00563 00564 while (true) { 00565 pal_status = pal_recv(socket, buf, len, recievedDataSize); 00566 if (pal_status == PAL_ERR_SOCKET_WOULD_BLOCK ) { // // The event was not a receive event - wait for next one 00567 pal_status = _wait_for_socket_event(); 00568 if (pal_status == PAL_ERR_RTOS_TIMEOUT ) { // Semaphore timeout means no event was triggered for _rcv_timeout ms so we return a WOULDBLOCK error according to blocking socket convention 00569 result = PAL_ERR_SOCKET_WOULD_BLOCK ; 00570 break; 00571 } else if (pal_status != PAL_SUCCESS) { // Should not happen - some unknown semaphore error 00572 result = pal_status; 00573 break; 00574 } 00575 // else: Semaphore signaled by event try receiving again 00576 00577 } else { // Either success, or error other than PAL_ERR_SOCKET_WOULD_BLOCK, return the status 00578 result = pal_status; 00579 break; 00580 } 00581 } 00582 00583 return result; 00584 00585 } 00586 00587 ftcd_comm_status_e FtcdCommSocket::_read_from_socket(void * data_out, int data_out_size) 00588 { 00589 palStatus_t pal_status = PAL_SUCCESS; 00590 size_t bytes_received = 0; 00591 size_t left_to_read = data_out_size; 00592 uint8_t* buffer = (uint8_t*)data_out; 00593 while (left_to_read > 0) { 00594 if (_connection_state != SOCKET_CONNECTION_ACCEPTED) { 00595 return FTCD_COMM_NETWORK_CONNECTION_CLOSED; 00596 } 00597 bytes_received = 0; 00598 pal_status = _recv(_client_socket, buffer, left_to_read, &bytes_received); 00599 if (pal_status == PAL_ERR_SOCKET_CONNECTION_CLOSED ) { 00600 // Drop current client 00601 _connection_state = SOCKET_WAIT_FOR_CONNECTION; 00602 return FTCD_COMM_NETWORK_CONNECTION_CLOSED; 00603 } 00604 else if (pal_status == PAL_ERR_SOCKET_WOULD_BLOCK ) { 00605 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket timeout"); 00606 return FTCD_COMM_NETWORK_TIMEOUT; 00607 } else if (pal_status != PAL_SUCCESS) { 00608 mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket error, (status = 0x%" PRIx32 ")", (uint32_t)pal_status); 00609 return FTCD_COMM_NETWORK_CONNECTION_ERROR; 00610 } 00611 buffer += bytes_received; 00612 if (left_to_read < bytes_received) { 00613 return FTCD_COMM_INTERNAL_ERROR; 00614 } 00615 left_to_read -= bytes_received; 00616 } 00617 00618 return FTCD_COMM_STATUS_SUCCESS; 00619 } 00620
Generated on Tue Jul 12 2022 20:20:59 by
