Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
pal_plat_network.c
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 #define _GNU_SOURCE // This is for ppoll found in poll.h 00018 #include "pal.h" 00019 #include "pal_plat_network.h" 00020 #include "pal_rtos.h" 00021 00022 #include <string.h> 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 #include <unistd.h> 00026 #include <string.h> 00027 #include <sys/time.h> 00028 #include <sys/types.h> 00029 #include <sys/socket.h> 00030 #include <netinet/in.h> 00031 #include <sys/ioctl.h> 00032 #include <net/if.h> 00033 #include <netdb.h> 00034 #include <ifaddrs.h> 00035 #include <errno.h> 00036 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00037 #include <pthread.h> 00038 #include <poll.h> 00039 #include <signal.h> 00040 #include <fcntl.h> 00041 #include <time.h> 00042 #include <assert.h> 00043 #endif 00044 00045 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00046 #include <netinet/tcp.h> 00047 #endif 00048 00049 // invalid socket based on posix 00050 #define PAL_LINUX_INVALID_SOCKET (-1) 00051 00052 00053 typedef struct palNetInterfaceName{ 00054 char interfaceName[PAL_NET_MAX_IF_NAME_LENGTH]; 00055 } palNetInterfaceName_t; 00056 00057 PAL_PRIVATE palNetInterfaceName_t s_palNetworkInterfacesSupported[PAL_MAX_SUPORTED_NET_INTERFACES]; 00058 00059 PAL_PRIVATE uint32_t s_palNumOfInterfaces = 0; 00060 PAL_PRIVATE uint32_t s_pal_network_initialized = 0; 00061 00062 PAL_PRIVATE palStatus_t translateErrorToPALError(int errnoValue) 00063 { 00064 palStatus_t status; 00065 switch (errnoValue) 00066 { 00067 case EAI_MEMORY: 00068 status = PAL_ERR_NO_MEMORY ; 00069 break; 00070 case EWOULDBLOCK: 00071 status = PAL_ERR_SOCKET_WOULD_BLOCK ; 00072 break; 00073 case ENOTSOCK: 00074 status = PAL_ERR_SOCKET_INVALID_VALUE ; 00075 break; 00076 case EPERM: 00077 case EACCES: 00078 status = PAL_ERR_SOCKET_OPERATION_NOT_PERMITTED ; 00079 break; 00080 case ETIMEDOUT: 00081 status = PAL_ERR_TIMEOUT_EXPIRED ; 00082 break; 00083 case EISCONN: 00084 status = PAL_ERR_SOCKET_ALREADY_CONNECTED ; 00085 break; 00086 case EINPROGRESS: 00087 status = PAL_ERR_SOCKET_IN_PROGRES ; 00088 break; 00089 case EALREADY: 00090 status = PAL_ERR_SOCKET_ALREADY_CONNECTED ; 00091 break; 00092 case EINVAL: 00093 status = PAL_ERR_SOCKET_INVALID_VALUE ; 00094 break; 00095 case EADDRINUSE: 00096 status = PAL_ERR_SOCKET_ADDRESS_IN_USE ; 00097 break; 00098 case ECONNABORTED: 00099 status = PAL_ERR_SOCKET_CONNECTION_ABORTED ; 00100 break; 00101 case ENOBUFS: 00102 case ENOMEM: 00103 status = PAL_ERR_SOCKET_NO_BUFFERS ; 00104 break; 00105 case EINTR: 00106 status = PAL_ERR_SOCKET_INTERRUPTED ; 00107 break; 00108 default: 00109 status = PAL_ERR_SOCKET_GENERIC ; 00110 break; 00111 } 00112 return status; 00113 } 00114 00115 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00116 static pthread_t s_pollThread = NULLPTR; 00117 static palMutexID_t s_mutexSocketCallbacks = 0; 00118 static palMutexID_t s_mutexSocketEventFilter = 0; 00119 static palSemaphoreID_t s_socketCallbackSemaphore = 0; 00120 static palSemaphoreID_t s_socketCallbackSignalSemaphore = 0; 00121 00122 00123 00124 // These must be updated only when protected by s_mutexSocketCallbacks 00125 static palAsyncSocketCallback_t s_callbacks[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0}; 00126 static void* s_callbackArgs[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = { 0 }; 00127 static struct pollfd s_fds[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {{0,0,0}}; 00128 static uint32_t s_callbackFilter[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0}; 00129 static nfds_t s_nfds = 0; 00130 static volatile bool s_socketThreadTerminateSignaled = false; 00131 00132 // The below function is the signal handler API, doing nothing. 00133 // The idea is to signal the asyncSocketManager thread with pthread_kill(s_pollThread, SIGUSR1) command 00134 // which make the ppoll API to be interrupted. 00135 00136 static uint64_t s_palUSR1Counter =0; 00137 static void sigusr2(int signo) { 00138 (void)signo; 00139 s_palUSR1Counter++; 00140 pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore); 00141 } 00142 00143 static uint64_t s_palIOCounter =0; 00144 00145 static void sig_io_handler(int signo) { 00146 (void)signo; 00147 00148 s_palIOCounter++; 00149 pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore); 00150 } 00151 00152 00153 static const unsigned int PAL_SOCKETS_TERMINATE = 10000; 00154 00155 00156 PAL_PRIVATE void clearSocketFilter( int socketFD) 00157 { 00158 palStatus_t result = PAL_SUCCESS; 00159 int i = 0; 00160 result = pal_osMutexWait(s_mutexSocketEventFilter, PAL_RTOS_WAIT_FOREVER); 00161 if (PAL_SUCCESS != result) 00162 { 00163 PAL_LOG(ERR, "error waiting for mutex"); // we want to zero the flag even if this fails beacuse it is better to get an extra event than miss one. 00164 } 00165 for (i = 0; i < PAL_NET_TEST_MAX_ASYNC_SOCKETS; i++) 00166 { 00167 00168 if (s_fds[i].fd == socketFD) 00169 { 00170 s_callbackFilter[i] = 0; 00171 break; 00172 } 00173 } 00174 result = pal_osMutexRelease(s_mutexSocketEventFilter); 00175 if (PAL_SUCCESS != result) 00176 { 00177 PAL_LOG(ERR, "error releasing mutex"); 00178 } 00179 } 00180 00181 00182 // Thread function. 00183 PAL_PRIVATE void asyncSocketManager(void const* arg) 00184 { 00185 PAL_UNUSED_ARG(arg); // unused 00186 int res; 00187 palAsyncSocketCallback_t callbacks[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0}; 00188 void* callbackArgs[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0}; 00189 struct pollfd fds[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {{0,0,0}}; 00190 nfds_t nfds = 0; 00191 struct sigaction s; 00192 sigset_t blockedSignals; 00193 palStatus_t result = PAL_SUCCESS; 00194 uint64_t lastIOCounter=0; 00195 uint64_t lastUSRCounter=0; 00196 00197 const struct timespec timeout_zero = {0, 0}; 00198 00199 // Initialize the signal handler. SIG_IGN and SIG_DFL do not work 00200 s.sa_handler = sigusr2; 00201 sigemptyset(&s.sa_mask); 00202 s.sa_flags = 0; 00203 sigaction(SIGUSR1, &s, NULL); 00204 00205 s.sa_handler = sig_io_handler; 00206 sigemptyset(&s.sa_mask); 00207 s.sa_flags = SA_RESTART ; 00208 sigaction(SIGIO, &s, NULL); 00209 00210 // Block the timer signal from interrupting ppoll(), as it does not have a signal handler. 00211 // The timer signal is already blocked on all the threads created after pal_init(), but 00212 // the ppoll() will change that situation with the given sigmask. 00213 // Without this, the libc's default signal handler will kick in and kill the process. 00214 sigemptyset(&blockedSignals); 00215 sigaddset(&blockedSignals, PAL_TIMER_SIGNAL); 00216 00217 s_pollThread = pthread_self(); // save the thread id for signal usage 00218 // Tell the calling thread that we have finished initialization 00219 result = pal_osSemaphoreRelease(s_socketCallbackSemaphore); 00220 if (result != PAL_SUCCESS) 00221 { 00222 PAL_LOG(ERR, "Error in async socket manager on semaphore release"); 00223 } 00224 00225 00226 while (result == PAL_SUCCESS) //As long as all goes well loop forever 00227 { 00228 // block until a SIGIO signal is received 00229 if (lastUSRCounter == s_palUSR1Counter) // no updates to the sockets that need to be polled (wait for next IO) - if there were updates skip waiting and proceeed to poll 00230 { 00231 pal_osSemaphoreWait(s_socketCallbackSignalSemaphore, PAL_RTOS_WAIT_FOREVER, NULL); 00232 } 00233 00234 // Critical section to update globals 00235 result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER); 00236 if (PAL_SUCCESS != result) 00237 { 00238 PAL_LOG(ERR, "Error in async socket manager on mutex wait"); 00239 break; 00240 } 00241 00242 // Check for thread termination request 00243 if(s_nfds == PAL_SOCKETS_TERMINATE) 00244 { 00245 result = pal_osMutexRelease(s_mutexSocketCallbacks); 00246 if (result != PAL_SUCCESS) 00247 { 00248 PAL_LOG(ERR, "Error in async socket manager on mutex release during termination"); 00249 } 00250 s_nfds = 0; // Reset s_ndfs 00251 s_socketThreadTerminateSignaled = true; // mark that the thread has receieved the termination request 00252 // Break out of while(1) 00253 break; 00254 } 00255 // Update the list of sockets to watch from the global list 00256 nfds = s_nfds; 00257 if(nfds) 00258 { 00259 memcpy(callbacks, s_callbacks, nfds*sizeof(callbacks[0])); 00260 memcpy(callbackArgs, s_callbackArgs, nfds * sizeof(void*)); 00261 memcpy(fds, s_fds, nfds*sizeof(fds[0])); 00262 00263 for (int i=0; i < nfds; i++) 00264 { 00265 fds[i].events = POLLIN|POLLOUT|POLLRDHUP|POLLERR; 00266 fds[i].revents = 0; 00267 s_callbackFilter[i] = 0; 00268 } 00269 } 00270 result = pal_osMutexRelease(s_mutexSocketCallbacks); 00271 if (result != PAL_SUCCESS) 00272 { 00273 PAL_LOG(ERR, "Error in async socket manager on mutex release"); 00274 break; 00275 } 00276 00277 // Wait for a socket event or pthread_kill(s_pollThread, SIGUSR1) event 00278 lastUSRCounter = s_palUSR1Counter; 00279 res = ppoll(&fds[0], nfds, &timeout_zero, &blockedSignals); 00280 00281 00282 // Notes: 00283 // If a POLLIN event occurred and recv from the socket results in 0 bytes being read, it means that 00284 // the remote socket was closed. Unless this is dealt with in the callback (for example by closing the 00285 // socket) the next call to ppoll will also immediately return with the same result. 00286 if(res >0 || errno == EINTR) 00287 { 00288 unsigned int i; 00289 errno = 0; 00290 // Some event was triggered, so iterate over all watched fds's and call the relevant callbacks. 00291 if (lastIOCounter< s_palIOCounter) 00292 { 00293 lastIOCounter = s_palIOCounter; 00294 for( i = 0; i < nfds; i++) 00295 { 00296 if(fds[i].revents) 00297 { 00298 uint32_t filter = POLLOUT|POLLHUP; // filter for specific event that is triggered for non-connected sockets- this event combination shouldn't exist in an active socket. 00299 00300 00301 if ((fds[i].revents != filter) && ((fds[i].revents != POLLOUT) || (fds[i].revents != s_callbackFilter[i])) ) // this is handlign for a special scenario when a specific event which shouldnt happen is sent to all unconnected sockets in Linux triggering an unwanted callback. 00302 { 00303 callbacks[i](callbackArgs[i]); 00304 } 00305 result = pal_osMutexWait(s_mutexSocketEventFilter, PAL_RTOS_WAIT_FOREVER); 00306 if (PAL_SUCCESS != result) 00307 { 00308 PAL_LOG(ERR, "error waiting for mutex"); 00309 } 00310 else 00311 { 00312 s_callbackFilter[i] = fds[i].revents; 00313 result = pal_osMutexRelease(s_mutexSocketEventFilter); 00314 if (PAL_SUCCESS != result) 00315 { 00316 PAL_LOG(ERR, "error releasing mutex"); 00317 } 00318 } 00319 00320 00321 } 00322 } 00323 } 00324 00325 00326 } 00327 else if (res == 0) 00328 { 00329 // Timeout 00330 } 00331 else 00332 { 00333 PAL_LOG(ERR, "Error in async socket manager"); 00334 } 00335 } // while 00336 } 00337 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00338 00339 PAL_PRIVATE palStatus_t pal_plat_SockAddrToSocketAddress(const palSocketAddress_t* palAddr, struct sockaddr* output) 00340 { 00341 palStatus_t result = PAL_SUCCESS; 00342 uint16_t port = 0; 00343 bool found = false; 00344 00345 result = pal_getSockAddrPort(palAddr, &port); 00346 if (result != PAL_SUCCESS) 00347 { 00348 return result; 00349 } 00350 00351 #if PAL_SUPPORT_IP_V4 00352 if (PAL_AF_INET == palAddr->addressType) 00353 { 00354 palIpV4Addr_t ipV4Addr = { 0 }; 00355 struct sockaddr_in* ip4addr = (struct sockaddr_in*)output; 00356 ip4addr->sin_family = AF_INET; 00357 ip4addr->sin_port = PAL_HTONS(port); 00358 result = pal_getSockAddrIPV4Addr(palAddr, ipV4Addr); 00359 if (result == PAL_SUCCESS) 00360 { 00361 memcpy(&ip4addr->sin_addr, ipV4Addr, sizeof(ip4addr->sin_addr)); 00362 } 00363 found = true; 00364 } 00365 00366 #endif // PAL_SUPPORT_IP_V4 00367 #if PAL_SUPPORT_IP_V6 00368 if (PAL_AF_INET6 == palAddr->addressType) 00369 { 00370 palIpV6Addr_t ipV6Addr = {0}; 00371 struct sockaddr_in6* ip6addr = (struct sockaddr_in6*)output; 00372 ip6addr->sin6_family = AF_INET6; 00373 ip6addr->sin6_scope_id = 0; // we assume there will not be several interfaces with the same IP. 00374 ip6addr->sin6_flowinfo = 0; 00375 ip6addr->sin6_port = PAL_HTONS(port); 00376 result = pal_getSockAddrIPV6Addr(palAddr, ipV6Addr); 00377 if (result == PAL_SUCCESS) 00378 { 00379 memcpy(&ip6addr->sin6_addr, ipV6Addr, sizeof(ip6addr->sin6_addr)); 00380 } 00381 found = true; 00382 } 00383 #endif 00384 00385 if (false == found) 00386 { 00387 return PAL_ERR_SOCKET_INVALID_ADDRESS ; 00388 } 00389 00390 return result; 00391 } 00392 00393 PAL_PRIVATE palStatus_t pal_plat_socketAddressToPalSockAddr(struct sockaddr* input, palSocketAddress_t* out, palSocketLength_t* length) 00394 { 00395 palStatus_t result = PAL_SUCCESS; 00396 bool found = false; 00397 00398 #if PAL_SUPPORT_IP_V4 00399 if (input->sa_family == AF_INET) 00400 { 00401 palIpV4Addr_t ipV4Addr; 00402 struct sockaddr_in* ip4addr = (struct sockaddr_in*)input; 00403 00404 memcpy(ipV4Addr, &ip4addr->sin_addr, PAL_IPV4_ADDRESS_SIZE); 00405 result = pal_setSockAddrIPV4Addr(out, ipV4Addr); 00406 if (result == PAL_SUCCESS) 00407 { 00408 result = pal_setSockAddrPort(out, PAL_NTOHS(ip4addr->sin_port)); 00409 } 00410 *length = sizeof(struct sockaddr_in); 00411 found = true; 00412 } 00413 #endif //PAL_SUPPORT_IP_V4 00414 #if PAL_SUPPORT_IP_V6 00415 if (input->sa_family == AF_INET6) 00416 { 00417 palIpV6Addr_t ipV6Addr; 00418 struct sockaddr_in6* ip6addr = (struct sockaddr_in6*)input; 00419 memcpy(ipV6Addr, &ip6addr->sin6_addr, PAL_IPV6_ADDRESS_SIZE); 00420 result = pal_setSockAddrIPV6Addr(out, ipV6Addr); 00421 if (result == PAL_SUCCESS) 00422 { 00423 result = pal_setSockAddrPort(out, PAL_NTOHS(ip6addr->sin6_port)); 00424 } 00425 *length = sizeof(struct sockaddr_in6); 00426 found = true; 00427 } 00428 #endif // PAL_SUPPORT_IP_V6 00429 00430 if (false == found) 00431 { // we got unspeicified in one of the tests, so Don't fail , but don't translate address. // re-chcking 00432 result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY ; 00433 } 00434 00435 return result; 00436 } 00437 00438 palStatus_t pal_plat_socketsInit(void* context) 00439 { 00440 PAL_UNUSED_ARG(context); 00441 palStatus_t result = PAL_SUCCESS; 00442 00443 if (s_pal_network_initialized == 1) 00444 { 00445 return PAL_SUCCESS; // already initialized. 00446 } 00447 00448 00449 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00450 00451 result = pal_osMutexCreate(&s_mutexSocketCallbacks); 00452 if (result != PAL_SUCCESS) 00453 { 00454 return result; 00455 } 00456 00457 result = pal_osMutexCreate(&s_mutexSocketEventFilter); 00458 if (PAL_SUCCESS != result) 00459 { 00460 return result; 00461 } 00462 00463 00464 result = pal_osSemaphoreCreate(0, &s_socketCallbackSignalSemaphore); 00465 if (result != PAL_SUCCESS) 00466 { 00467 // todo: clean up the mess created so far 00468 return result; 00469 } 00470 00471 // Sleep at first wait 00472 result = pal_osSemaphoreCreate(0, &s_socketCallbackSemaphore); 00473 if (result != PAL_SUCCESS) 00474 { 00475 if (pal_osMutexDelete(&s_mutexSocketCallbacks) != PAL_SUCCESS) //cleanup allocated resources 00476 { 00477 // TODO print error using logging mechanism when available. 00478 } 00479 return result; 00480 } 00481 00482 s_socketThreadTerminateSignaled = false; 00483 palThreadID_t threadID = NULLPTR; 00484 result = pal_osThreadCreateWithAlloc(asyncSocketManager, NULL, PAL_osPriorityReservedSockets , PAL_NET_TEST_ASYNC_SOCKET_MANAGER_THREAD_STACK_SIZE, NULL, &threadID); 00485 if (PAL_SUCCESS != result) 00486 { 00487 if (PAL_ERR_RTOS_PRIORITY == result) 00488 { 00489 result = PAL_ERR_SOCKET_OPERATION_NOT_PERMITTED ; 00490 } 00491 else 00492 { 00493 result = PAL_ERR_SOCKET_GENERIC ; 00494 } 00495 } 00496 else 00497 { 00498 // Wait here for the thread to be initialized. 00499 result = pal_osSemaphoreWait(s_socketCallbackSemaphore, PAL_RTOS_WAIT_FOREVER, NULL); 00500 if (PAL_SUCCESS != result) 00501 { 00502 goto end; 00503 } 00504 result = pal_osSemaphoreDelete(&s_socketCallbackSemaphore); 00505 if (PAL_SUCCESS != result) 00506 { 00507 goto end; 00508 } 00509 } 00510 #endif 00511 00512 end: 00513 if (PAL_SUCCESS == result) 00514 { 00515 s_pal_network_initialized = 1; 00516 } 00517 00518 00519 return result; 00520 } 00521 00522 palStatus_t pal_plat_registerNetworkInterface (void* context, uint32_t* interfaceIndex) 00523 { 00524 palStatus_t result = PAL_SUCCESS; 00525 uint32_t index = 0; 00526 bool found = false; 00527 00528 for (index = 0; index < s_palNumOfInterfaces; index++) // if specific context already registered return existing index instead of registering again. 00529 { 00530 if (memcmp(s_palNetworkInterfacesSupported[index].interfaceName, (const char *)context, strlen(s_palNetworkInterfacesSupported[index].interfaceName)) == 0) 00531 { 00532 found = true; 00533 *interfaceIndex = index; 00534 break; 00535 } 00536 } 00537 if (false == found) 00538 { 00539 if (s_palNumOfInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES) 00540 { 00541 strncpy(s_palNetworkInterfacesSupported[s_palNumOfInterfaces].interfaceName, (const char *)context, PAL_NET_MAX_IF_NAME_LENGTH-1); 00542 s_palNetworkInterfacesSupported[s_palNumOfInterfaces].interfaceName[PAL_NET_MAX_IF_NAME_LENGTH-1] = '\0'; 00543 *interfaceIndex = s_palNumOfInterfaces; 00544 ++s_palNumOfInterfaces; 00545 } 00546 else 00547 { 00548 result = PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED ; 00549 } 00550 } 00551 00552 return result; 00553 } 00554 00555 palStatus_t pal_plat_socketsTerminate (void* context) 00556 { 00557 PAL_UNUSED_ARG(context); 00558 palStatus_t result = PAL_SUCCESS; 00559 palStatus_t firstError = PAL_SUCCESS; 00560 00561 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00562 // Critical section to update globals 00563 result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER); 00564 if (result != PAL_SUCCESS) 00565 { 00566 // TODO print error using logging mechanism when available. 00567 firstError = result; 00568 } 00569 00570 s_nfds = PAL_SOCKETS_TERMINATE; 00571 result = pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore); 00572 if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError)) 00573 { 00574 // TODO print error using logging mechanism when available. 00575 firstError = result; 00576 } 00577 // Tell the poll thread to interrupt so that it can check for termination. 00578 if(s_pollThread != NULLPTR) 00579 { 00580 pthread_kill(s_pollThread, SIGUSR1); 00581 } 00582 00583 result = pal_osMutexRelease(s_mutexSocketCallbacks); 00584 if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError)) 00585 { 00586 // TODO print error using logging mechanism when available. 00587 firstError = result; 00588 } 00589 00590 while (!s_socketThreadTerminateSignaled) 00591 { 00592 pal_osDelay(10); 00593 } 00594 00595 result = pal_osSemaphoreDelete(&s_socketCallbackSignalSemaphore); 00596 if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError)) 00597 { 00598 // TODO print error using logging mechanism when available. 00599 firstError = result; 00600 } 00601 00602 result = pal_osMutexDelete(&s_mutexSocketEventFilter); 00603 if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError)) 00604 { 00605 // TODO print error using logging mechanism when available. 00606 firstError = result; 00607 } 00608 00609 result = pal_osMutexDelete(&s_mutexSocketCallbacks); 00610 if ((PAL_SUCCESS != result ) && (PAL_SUCCESS == firstError)) 00611 { 00612 // TODO print error using logging mechanism when available. 00613 firstError = result; 00614 } 00615 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00616 00617 s_pal_network_initialized = 0; 00618 00619 return firstError; 00620 } 00621 00622 /* 00623 * NOTE!!!! 00624 * When creating socket in Linux, we ignore interfaceNum provided. 00625 * The socket should be bound to interface pal_plat_bind API (bind to address reflects the bound between 00626 * socket and interface). 00627 */ 00628 palStatus_t pal_plat_socket (palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* sockt) 00629 { 00630 int result = PAL_SUCCESS; 00631 intptr_t sockfd; 00632 int sockBehavior = 0; 00633 00634 PAL_VALIDATE_ARGUMENTS(interfaceNum >= s_palNumOfInterfaces && PAL_NET_DEFAULT_INTERFACE != interfaceNum); 00635 00636 // These are the same in Linux 00637 if(type == PAL_SOCK_STREAM_SERVER ) 00638 { 00639 type = PAL_SOCK_STREAM; 00640 } 00641 00642 // Compile time check that PAL values are the same as Linux values 00643 PAL_ASSERT_STATIC(AF_INET == PAL_AF_INET); 00644 PAL_ASSERT_STATIC(AF_INET6 == PAL_AF_INET6 ); 00645 PAL_ASSERT_STATIC(AF_UNSPEC == PAL_AF_UNSPEC); 00646 PAL_ASSERT_STATIC(SOCK_DGRAM == (unsigned int)PAL_SOCK_DGRAM ); 00647 PAL_ASSERT_STATIC(SOCK_STREAM == (unsigned int)PAL_SOCK_STREAM); 00648 00649 if (nonBlockingSocket) 00650 { 00651 sockBehavior = SOCK_NONBLOCK; 00652 } 00653 00654 // SOCK_NONBLOCK since Linux 2.6.27 00655 sockfd = socket(domain, type | sockBehavior , 0); 00656 // Note - though it is not an error, if we get sockfd == 0 then we probably (accidentally closed fd 0 somewhere else) 00657 if (sockfd == PAL_LINUX_INVALID_SOCKET) 00658 { 00659 result = translateErrorToPALError(errno); 00660 } 00661 else 00662 { 00663 *sockt = (palSocket_t )sockfd; 00664 } 00665 return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized) 00666 } 00667 00668 00669 // Assume input timeout value is in milliseconds. 00670 palStatus_t pal_plat_setSocketOptions (palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength) 00671 { 00672 int result = PAL_SUCCESS; 00673 int linuxName; 00674 PAL_UNUSED_ARG(optionLength); 00675 00676 00677 struct timeval timeout; 00678 timeout.tv_sec = 0; 00679 timeout.tv_usec = 0; 00680 00681 switch (optionName) 00682 { 00683 case PAL_SO_SNDTIMEO : 00684 linuxName = SO_SNDTIMEO; 00685 timeout.tv_sec = (*(int *)optionValue)/1000 ; 00686 timeout.tv_usec = ((*(int *)optionValue)%1000)*1000 ; 00687 break; 00688 case PAL_SO_RCVTIMEO : 00689 linuxName = SO_RCVTIMEO; 00690 timeout.tv_sec = (*(int *)optionValue)/1000 ; 00691 timeout.tv_usec = ((*(int *)optionValue)%1000)*1000 ; 00692 break; 00693 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00694 case PAL_SO_KEEPALIVE : 00695 linuxName = SO_KEEPALIVE; 00696 break; 00697 case PAL_SO_KEEPIDLE : 00698 linuxName = TCP_KEEPIDLE; 00699 break; 00700 case PAL_SO_KEEPINTVL : 00701 linuxName = TCP_KEEPINTVL; 00702 break; 00703 #endif 00704 case PAL_SO_REUSEADDR: 00705 linuxName = SO_REUSEADDR; 00706 break; 00707 default: 00708 // Unsupported option 00709 result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED ; 00710 } 00711 00712 if (PAL_SUCCESS == result) 00713 { 00714 if (PAL_SO_SNDTIMEO == optionName || PAL_SO_RCVTIMEO == optionName) 00715 { 00716 result = setsockopt ((intptr_t)socket, SOL_SOCKET, linuxName, &timeout, sizeof(timeout)); 00717 } 00718 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT 00719 else if (PAL_SO_KEEPIDLE == optionName || PAL_SO_KEEPINTVL == optionName) 00720 { 00721 result = setsockopt ((intptr_t)socket, SOL_TCP, linuxName, (int *)optionValue, optionLength); 00722 } 00723 #endif 00724 else 00725 { 00726 result = setsockopt ((intptr_t)socket, SOL_SOCKET, linuxName, (int *)optionValue, optionLength); 00727 } 00728 00729 if(-1 == result) 00730 { 00731 result = translateErrorToPALError(errno); 00732 } 00733 } 00734 00735 return result; 00736 } 00737 00738 palStatus_t pal_plat_isNonBlocking (palSocket_t socket, bool* isNonBlocking) 00739 { 00740 int flags = fcntl((intptr_t)socket, F_GETFL); 00741 00742 if (0 != (flags & O_NONBLOCK)) 00743 { 00744 *isNonBlocking = true; 00745 } 00746 else 00747 { 00748 *isNonBlocking = false; 00749 } 00750 return PAL_SUCCESS; 00751 } 00752 00753 00754 palStatus_t pal_plat_bind (palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength) 00755 { 00756 int result = PAL_SUCCESS; 00757 int res = 0; 00758 struct sockaddr_storage internalAddr = {0} ; 00759 00760 result = pal_plat_SockAddrToSocketAddress(myAddress, (struct sockaddr *)&internalAddr); 00761 if (result == PAL_SUCCESS) 00762 { 00763 res = bind((intptr_t)socket, (struct sockaddr *)&internalAddr, addressLength); 00764 if (res == -1) 00765 { 00766 result = translateErrorToPALError(errno); 00767 } 00768 } 00769 00770 return result; 00771 } 00772 00773 00774 palStatus_t pal_plat_receiveFrom (palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived) 00775 { 00776 palStatus_t result = PAL_SUCCESS; 00777 ssize_t res; 00778 struct sockaddr_storage internalAddr; 00779 socklen_t addrlen; 00780 00781 clearSocketFilter((intptr_t)socket); 00782 addrlen = sizeof(struct sockaddr_storage); 00783 res = recvfrom((intptr_t)socket, buffer, length, 0 ,(struct sockaddr *)&internalAddr, &addrlen); 00784 if(res == -1) 00785 { 00786 result = translateErrorToPALError(errno); 00787 } 00788 else // only return address / bytesReceived in case of success 00789 { 00790 if ((NULL != from) && (NULL != fromLength)) 00791 { 00792 result = pal_plat_socketAddressToPalSockAddr((struct sockaddr *)&internalAddr, from, fromLength); 00793 } 00794 *bytesReceived = res; 00795 } 00796 00797 return result; 00798 } 00799 00800 palStatus_t pal_plat_sendTo (palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent) 00801 { 00802 palStatus_t result = PAL_SUCCESS; 00803 ssize_t res; 00804 00805 clearSocketFilter((intptr_t)socket); 00806 res = sendto((intptr_t)socket, buffer, length, 0, (struct sockaddr *)to, toLength); 00807 if(res == -1) 00808 { 00809 result = translateErrorToPALError(errno); 00810 } 00811 else 00812 { 00813 *bytesSent = res; 00814 } 00815 00816 return result; 00817 } 00818 00819 palStatus_t pal_plat_close (palSocket_t* socket) 00820 { 00821 palStatus_t result = PAL_SUCCESS; 00822 int res; 00823 unsigned int i,j; 00824 00825 if (*socket == (void *)PAL_LINUX_INVALID_SOCKET) // socket already closed - return success. 00826 { 00827 PAL_LOG(DBG, "socket close called on socket which was already closed"); 00828 return result; 00829 } 00830 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00831 // Critical section to update globals 00832 result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER); 00833 if (result != PAL_SUCCESS) 00834 { 00835 // TODO print error using logging mechanism when available. 00836 return result; 00837 } 00838 00839 for(i= 0 ; i < s_nfds; i++) 00840 { 00841 // check if we have we found the socket being closed 00842 if (s_fds[i].fd == (intptr_t)*socket) 00843 { 00844 // Remove from async socket list 00845 // Close the gap in the socket data structures. 00846 for(j = i; j < s_nfds - 1; j++) 00847 { 00848 s_fds[j].fd = s_fds[j+1].fd; 00849 s_fds[j].events = s_fds[j+1].events; 00850 s_callbacks[j] = s_callbacks[j+1]; 00851 s_callbackArgs[j] = s_callbackArgs[j+1]; 00852 } 00853 // Blank out the last one 00854 s_fds[j].fd = 0; 00855 s_callbacks[j] = 0; 00856 s_callbackArgs[j] = 0; 00857 s_nfds--; 00858 // Tell the poll thread to remove the socket 00859 pthread_kill(s_pollThread, SIGUSR1); 00860 break; 00861 } 00862 } 00863 result = pal_osMutexRelease(s_mutexSocketCallbacks); 00864 if (result != PAL_SUCCESS) 00865 { 00866 // TODO print error using logging mechanism when available. 00867 return result; 00868 } 00869 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00870 // In Linux it is ok to close a socket while it is being polled, but may not be on other os's 00871 res = close((intptr_t) *socket); 00872 if(res == -1) 00873 result = translateErrorToPALError(errno); 00874 else 00875 { 00876 *socket = (void *)PAL_LINUX_INVALID_SOCKET; 00877 } 00878 return result; 00879 } 00880 00881 palStatus_t pal_plat_getNumberOfNetInterfaces ( uint32_t* numInterfaces) 00882 { 00883 *numInterfaces = s_palNumOfInterfaces; 00884 return PAL_SUCCESS; 00885 } 00886 00887 palStatus_t pal_plat_getNetInterfaceInfo (uint32_t interfaceNum, palNetInterfaceInfo_t * interfaceInfo) 00888 { 00889 palStatus_t result = PAL_SUCCESS; 00890 struct ifaddrs *ifap,*ifa; 00891 int res,n; 00892 uint32_t found = 0; 00893 00894 PAL_VALIDATE_ARGUMENTS (interfaceNum >= s_palNumOfInterfaces); 00895 00896 res = getifaddrs(&ifap); 00897 if(res < 0) 00898 { 00899 result = translateErrorToPALError(errno); 00900 } 00901 else 00902 { 00903 for (ifa = ifap, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) 00904 { 00905 if (ifa->ifa_addr == NULL) 00906 continue; 00907 int family = ifa->ifa_addr->sa_family; 00908 if (strcmp(s_palNetworkInterfacesSupported[interfaceNum].interfaceName, ifa->ifa_name) == 0) 00909 { 00910 if (family == AF_INET || family == AF_INET6) 00911 { 00912 found = 1; 00913 if (family == AF_INET) 00914 { 00915 interfaceInfo->addressSize = sizeof(struct sockaddr_in); 00916 } 00917 else 00918 { 00919 interfaceInfo->addressSize = sizeof(struct sockaddr_in6); 00920 } 00921 00922 strncpy(interfaceInfo->interfaceName, s_palNetworkInterfacesSupported[interfaceNum].interfaceName, strlen(s_palNetworkInterfacesSupported[interfaceNum].interfaceName)); 00923 00924 result = pal_plat_socketAddressToPalSockAddr(ifa->ifa_addr, &interfaceInfo->address, &interfaceInfo->addressSize); 00925 00926 break; 00927 } 00928 } 00929 } 00930 // free what was allocated by getifaddrs 00931 freeifaddrs(ifap); 00932 } 00933 00934 //interface not found error 00935 if (found != 1 && result == PAL_SUCCESS) 00936 { 00937 PAL_LOG(ERR, "Network failed reading interface info"); 00938 result = PAL_ERR_GENERIC_FAILURE; 00939 } 00940 00941 return result; 00942 } 00943 00944 00945 #if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported. 00946 palStatus_t pal_plat_listen (palSocket_t socket, int backlog) 00947 { 00948 palStatus_t result = PAL_SUCCESS; 00949 int res; 00950 00951 res = listen((intptr_t)socket,backlog); 00952 if(res == -1) 00953 { 00954 result = translateErrorToPALError(errno); 00955 } 00956 return result; 00957 } 00958 00959 00960 palStatus_t pal_plat_accept (palSocket_t socket, palSocketAddress_t * address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket) 00961 { 00962 intptr_t res = 0; 00963 palStatus_t result = PAL_SUCCESS; 00964 struct sockaddr_storage internalAddr = {0} ; 00965 socklen_t internalAddrLen = sizeof(internalAddr); 00966 00967 // XXX: the whole addressLen -concept is broken as the address is fixed size anyway. 00968 if (*addressLen < sizeof(palSocketAddress_t)) 00969 { 00970 return PAL_ERR_SOCKET_INVALID_ADDRESS ; 00971 } 00972 00973 res = accept((intptr_t)socket,(struct sockaddr *)&internalAddr, &internalAddrLen); 00974 if(res == -1) 00975 { 00976 result = translateErrorToPALError(errno); 00977 } 00978 else 00979 { 00980 *acceptedSocket = (palSocket_t*)res; 00981 *addressLen = sizeof(palSocketAddress_t); 00982 result = pal_plat_socketAddressToPalSockAddr((struct sockaddr *)&internalAddr, address, &internalAddrLen); 00983 } 00984 00985 return result; 00986 } 00987 00988 00989 palStatus_t pal_plat_connect (palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen) 00990 { 00991 int result = PAL_SUCCESS; 00992 int res; 00993 struct sockaddr_storage internalAddr = {0} ; 00994 00995 result = pal_plat_SockAddrToSocketAddress(address, (struct sockaddr *)&internalAddr); 00996 if (result == PAL_SUCCESS) 00997 { 00998 res = connect((intptr_t)socket,(struct sockaddr *)&internalAddr, addressLen); 00999 if(res == -1) 01000 { 01001 result = translateErrorToPALError(errno); 01002 } 01003 } 01004 01005 return result; 01006 } 01007 01008 palStatus_t pal_plat_recv (palSocket_t socket, void *buffer, size_t len, size_t* recievedDataSize) 01009 { 01010 palStatus_t result = PAL_SUCCESS; 01011 ssize_t res; 01012 01013 clearSocketFilter((intptr_t)socket); 01014 res = recv((intptr_t)socket, buffer, len, 0); 01015 if(res == -1) 01016 { 01017 result = translateErrorToPALError(errno); 01018 } 01019 else 01020 { 01021 if (0 == res) 01022 { 01023 result = PAL_ERR_SOCKET_CONNECTION_CLOSED ; 01024 } 01025 *recievedDataSize = res; 01026 } 01027 return result; 01028 } 01029 01030 palStatus_t pal_plat_send (palSocket_t socket, const void *buf, size_t len, size_t *sentDataSize) 01031 { 01032 palStatus_t result = PAL_SUCCESS; 01033 ssize_t res; 01034 01035 clearSocketFilter((intptr_t)socket); 01036 01037 res = send((intptr_t)socket, buf, len, 0); 01038 if(res == -1) 01039 { 01040 result = translateErrorToPALError(errno); 01041 } 01042 else 01043 { 01044 *sentDataSize = res; 01045 } 01046 01047 return result; 01048 } 01049 01050 #endif //PAL_NET_TCP_AND_TLS_SUPPORT 01051 01052 01053 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 01054 palStatus_t pal_plat_asynchronousSocket (palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* callbackArgument, palSocket_t* socket) 01055 { 01056 01057 int err; 01058 int flags; 01059 palStatus_t result = pal_plat_socket (domain, type, nonBlockingSocket, interfaceNum, socket); 01060 01061 01062 01063 // initialize the socket to be ASYNC so we get SIGIO's for it 01064 // XXX: this needs to be conditionalized as the blocking IO might have some use also. 01065 err = fcntl((intptr_t)*socket, F_SETOWN, getpid()); 01066 assert(err != -1); 01067 01068 flags = fcntl((intptr_t)*socket, F_GETFL, 0); 01069 assert(flags >= 0); 01070 01071 flags |= O_ASYNC; 01072 01073 err = fcntl((intptr_t)*socket, F_SETFL, flags); 01074 01075 if (err == -1) 01076 { 01077 result = translateErrorToPALError(errno); 01078 } 01079 01080 01081 if (result == PAL_SUCCESS) 01082 { 01083 // Critical section to update globals 01084 result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER); 01085 if (result != PAL_SUCCESS) 01086 { 01087 // TODO print error using logging mechanism when available. 01088 return result; 01089 } 01090 s_fds[s_nfds].fd = (intptr_t)*socket; 01091 s_fds[s_nfds].events = POLLIN|POLLERR; //TODO POLLOUT missing is not documented 01092 s_callbacks[s_nfds] = callback; 01093 s_callbackArgs[s_nfds] = callbackArgument; 01094 s_nfds++; 01095 result = pal_osMutexRelease(s_mutexSocketCallbacks); 01096 if (result != PAL_SUCCESS) 01097 { 01098 // TODO print error using logging mechanism when available. 01099 return result; 01100 } 01101 // Tell the poll thread to add the new socket 01102 pthread_kill(s_pollThread, SIGUSR1); 01103 } 01104 01105 return result; 01106 01107 } 01108 01109 #endif 01110 01111 #if PAL_NET_DNS_SUPPORT 01112 01113 palStatus_t pal_plat_getAddressInfo (const char *url, palSocketAddress_t *address, palSocketLength_t* length) 01114 { 01115 palStatus_t result = PAL_SUCCESS; 01116 palSocketAddress_t localAddress = {0}; 01117 palSocketAddress_t zeroAddress = {0}; 01118 struct addrinfo *pAddrInf = NULL; 01119 struct addrinfo hints = {0}; 01120 int res; 01121 int supportedAddressType1 = 0; 01122 int supportedAddressType2 = 0; 01123 hints.ai_family = AF_UNSPEC; 01124 01125 #if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY 01126 supportedAddressType1 = AF_INET; 01127 supportedAddressType2 = AF_INET6; 01128 hints.ai_family = AF_UNSPEC; 01129 #elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY 01130 supportedAddressType1 = AF_INET; 01131 supportedAddressType2 = AF_INET; 01132 hints.ai_family = AF_INET; 01133 #elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY 01134 supportedAddressType1 = AF_INET6; 01135 supportedAddressType2 = AF_INET6; 01136 hints.ai_family = AF_INET6; 01137 #else 01138 #error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value. 01139 #endif 01140 01141 res = getaddrinfo(url, NULL, &hints, &pAddrInf); 01142 if(res < 0) 01143 { 01144 result = translateErrorToPALError(errno); 01145 } 01146 else 01147 { 01148 if ((pAddrInf != NULL) && (pAddrInf->ai_family == supportedAddressType1 || pAddrInf->ai_family == supportedAddressType2)) 01149 { 01150 result = pal_plat_socketAddressToPalSockAddr((struct sockaddr*)pAddrInf->ai_addr, &localAddress, length); 01151 01152 if (0 == memcmp(localAddress.addressData, zeroAddress.addressData, PAL_NET_MAX_ADDR_SIZE) ) // invalid 0 address 01153 { 01154 result = PAL_ERR_SOCKET_DNS_ERROR ; 01155 } 01156 else 01157 { 01158 *address = localAddress; 01159 } 01160 } 01161 else 01162 { 01163 result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY ; 01164 } 01165 01166 freeaddrinfo(pAddrInf); 01167 } 01168 01169 return result; 01170 } 01171 01172 #endif
Generated on Tue Jul 12 2022 19:12:14 by 1.7.2