Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_plat_network.c Source File

pal_plat_network.c

00001 /*
00002 * Copyright (c) 2016 ARM Limited. All rights reserved.
00003 * SPDX-License-Identifier: Apache-2.0
00004 * Licensed under the Apache License, Version 2.0 (the License); you may
00005 * 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, WITHOUT
00012 * 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;
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 
00131 // The below function is the signal handler API, doing nothing.
00132 // The idea is to signal the asyncSocketManager thread with pthread_kill(s_pollThread, SIGUSR1) command
00133 // which make the ppoll API to be interrupted.
00134 
00135 static uint64_t s_palUSR1Counter =0;
00136 static void sigusr2(int signo) {
00137     (void)signo;
00138     s_palUSR1Counter++;
00139     pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore);
00140 }
00141 
00142 static uint64_t s_palIOCounter =0;
00143 
00144 static void sig_io_handler(int signo) {
00145     (void)signo;
00146 
00147     s_palIOCounter++;
00148     pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore);
00149 }
00150 
00151 
00152 static const unsigned int PAL_SOCKETS_TERMINATE = 10000;
00153 
00154 
00155 PAL_PRIVATE void clearSocketFilter( int socketFD)
00156 {
00157     palStatus_t result = PAL_SUCCESS;
00158     int i = 0;
00159     result = pal_osMutexWait(s_mutexSocketEventFilter, PAL_RTOS_WAIT_FOREVER);
00160     if (PAL_SUCCESS != result)
00161     {
00162         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.
00163     }
00164     for (i = 0; i < PAL_NET_TEST_MAX_ASYNC_SOCKETS; i++)
00165     {
00166 
00167         if (s_fds[i].fd == socketFD)
00168         {
00169             s_callbackFilter[i] = 0;
00170             break;
00171         }
00172     }
00173     result = pal_osMutexRelease(s_mutexSocketEventFilter);
00174     if (PAL_SUCCESS != result)
00175     {
00176         PAL_LOG(ERR, "error releasing mutex");
00177     }
00178 }
00179 
00180 
00181 // Thread function.
00182 static void* asyncSocketManager(void *arg)
00183 {
00184     PAL_UNUSED_ARG(arg); // unused
00185     int res;
00186     palAsyncSocketCallback_t  callbacks[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0};
00187     void* callbackArgs[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0};
00188     struct pollfd fds[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {{0,0,0}};
00189     nfds_t nfds = 0;
00190     struct sigaction s;
00191     palStatus_t result = PAL_SUCCESS;
00192     uint64_t lastIOCounter=0;
00193     uint64_t lastUSRCounter=0;
00194 
00195     const struct timespec timeout_zero = {0, 0};
00196 
00197     // Initialize the signal handler. SIG_IGN and SIG_DFL do not work
00198     s.sa_handler = sigusr2;
00199     sigemptyset(&s.sa_mask);
00200     s.sa_flags = 0;
00201     sigaction(SIGUSR1, &s, NULL);
00202 
00203     s.sa_handler = sig_io_handler;
00204     sigemptyset(&s.sa_mask);
00205     s.sa_flags =  SA_RESTART ;
00206     sigaction(SIGIO, &s, NULL);
00207 
00208     // Tell the calling thread that we have finished initialization
00209     result = pal_osSemaphoreRelease(s_socketCallbackSemaphore);
00210     if (result != PAL_SUCCESS)
00211     {
00212         PAL_LOG(ERR, "Error in async socket manager on semaphore release");
00213     }
00214 
00215 
00216     while (result == PAL_SUCCESS) //As long as all goes well loop forever
00217     {
00218         // block until a SIGIO signal is received
00219         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
00220         {
00221             pal_osSemaphoreWait(s_socketCallbackSignalSemaphore, PAL_RTOS_WAIT_FOREVER, NULL);
00222         }
00223 
00224         // Critical section to update globals
00225         result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
00226         if (PAL_SUCCESS != result)
00227         {
00228             PAL_LOG(ERR, "Error in async socket manager on mutex wait");
00229             break;
00230         }
00231 
00232         // Check for thread termination request
00233         if(s_nfds == PAL_SOCKETS_TERMINATE)
00234         {
00235             result = pal_osMutexRelease(s_mutexSocketCallbacks);
00236             if (result != PAL_SUCCESS)
00237             {
00238                 PAL_LOG(ERR, "Error in async socket manager on mutex release during termination");
00239             }
00240             s_nfds = 0; // Reset s_ndfs
00241             // Break out of while(1)
00242             break;
00243         }
00244         // Update the list of sockets to watch from the global list
00245         nfds = s_nfds;
00246         if(nfds)
00247         {
00248             memcpy(callbacks, s_callbacks, nfds*sizeof(callbacks[0]));
00249             memcpy(callbackArgs, s_callbackArgs, nfds * sizeof(void*));
00250             memcpy(fds, s_fds, nfds*sizeof(fds[0]));
00251 
00252             for (int i=0; i < nfds; i++)
00253             {
00254                 fds[i].events = POLLIN|POLLOUT|POLLRDHUP|POLLERR;
00255                 fds[i].revents = 0;
00256                 s_callbackFilter[i] = 0;
00257             }
00258         }
00259         result = pal_osMutexRelease(s_mutexSocketCallbacks);
00260         if (result != PAL_SUCCESS)
00261         {
00262             PAL_LOG(ERR, "Error in async socket manager on mutex release");
00263             break;
00264         }
00265 
00266         // Wait for a socket event or pthread_kill(s_pollThread, SIGUSR1) event
00267         lastUSRCounter = s_palUSR1Counter;
00268         res = ppoll(&fds[0], nfds, &timeout_zero, &s.sa_mask);
00269 
00270 
00271         // Notes:
00272         // If a POLLIN event occurred and recv from the socket results in 0 bytes being read, it means that
00273         // the remote socket was closed. Unless this is dealt with in the callback (for example by closing the
00274         // socket) the next call to ppoll will also immediately return with the same result.
00275         if(res >0 || errno == EINTR)
00276         {
00277             unsigned int i;
00278             errno = 0;
00279             // Some event was triggered, so iterate over all watched fds's and call the relevant callbacks.
00280                 if (lastIOCounter< s_palIOCounter)
00281                 {
00282                     lastIOCounter = s_palIOCounter;
00283                     for( i = 0; i < nfds; i++)
00284                     {
00285                         if(fds[i].revents)
00286                         {
00287                             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.
00288 
00289 
00290                             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.
00291                             {
00292                                 callbacks[i](callbackArgs[i]);
00293                             }
00294                             result = pal_osMutexWait(s_mutexSocketEventFilter, PAL_RTOS_WAIT_FOREVER);
00295                             if (PAL_SUCCESS != result)
00296                             {
00297                                 PAL_LOG(ERR, "error waiting for mutex");
00298                             }
00299                             else
00300                             {
00301                                 s_callbackFilter[i] = fds[i].revents;
00302                                 result = pal_osMutexRelease(s_mutexSocketEventFilter);
00303                                 if (PAL_SUCCESS != result)
00304                                 {
00305                                     PAL_LOG(ERR, "error releasing mutex");
00306                                 }
00307                             }
00308 
00309 
00310                         }
00311                     }
00312                 }
00313 
00314 
00315         }
00316         else if (res == 0)
00317         {
00318             // Timeout
00319         }
00320         else
00321         {
00322             PAL_LOG(ERR, "Error in async socket manager");
00323         }
00324     }  // while
00325 
00326     return NULL;
00327 }
00328 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
00329 
00330 PAL_PRIVATE palStatus_t pal_plat_SockAddrToSocketAddress(const palSocketAddress_t* palAddr, struct sockaddr* output)
00331 {
00332     palStatus_t result = PAL_SUCCESS;
00333     uint16_t port = 0;
00334 
00335     result = pal_getSockAddrPort(palAddr, &port);
00336     if (result != PAL_SUCCESS)
00337     {
00338         return result;
00339     }
00340 
00341     if (PAL_AF_INET == palAddr->addressType)
00342     {
00343         palIpV4Addr_t ipV4Addr  = {0};
00344         struct sockaddr_in* ip4addr = (struct sockaddr_in*)output;
00345         ip4addr->sin_family = AF_INET;
00346         ip4addr->sin_port = PAL_HTONS(port);
00347         result = pal_getSockAddrIPV4Addr(palAddr, ipV4Addr);
00348         if (result == PAL_SUCCESS)
00349         {
00350             memcpy(&ip4addr->sin_addr, ipV4Addr, sizeof(ip4addr->sin_addr));
00351         }
00352     }
00353     else if (PAL_AF_INET6  == palAddr->addressType)
00354     {
00355         palIpV6Addr_t ipV6Addr = {0};
00356         struct sockaddr_in6* ip6addr = (struct sockaddr_in6*)output;
00357         ip6addr->sin6_family = AF_INET6;
00358         ip6addr->sin6_scope_id = 0; // we assume there will not be several interfaces with the same IP.
00359         ip6addr->sin6_flowinfo = 0;
00360         ip6addr->sin6_port = PAL_HTONS(port);
00361         result = pal_getSockAddrIPV6Addr(palAddr, ipV6Addr);
00362         if (result == PAL_SUCCESS)
00363         {
00364             memcpy(&ip6addr->sin6_addr, ipV6Addr, sizeof(ip6addr->sin6_addr));
00365         }
00366     }
00367 
00368     return result;
00369 }
00370 
00371 PAL_PRIVATE palStatus_t pal_plat_socketAddressToPalSockAddr(struct sockaddr* input, palSocketAddress_t* out, palSocketLength_t* length)
00372 {
00373     palStatus_t result = PAL_SUCCESS;
00374 
00375     if (input->sa_family == AF_INET)
00376     {
00377         palIpV4Addr_t ipV4Addr;
00378         struct sockaddr_in* ip4addr = (struct sockaddr_in*)input;
00379 
00380         memcpy(ipV4Addr, &ip4addr->sin_addr, PAL_IPV4_ADDRESS_SIZE);
00381         result = pal_setSockAddrIPV4Addr(out, ipV4Addr);
00382         if (result == PAL_SUCCESS)
00383         {
00384             result = pal_setSockAddrPort(out, PAL_NTOHS(ip4addr->sin_port));
00385         }
00386         *length = sizeof(struct sockaddr_in);
00387     }
00388     else if (input->sa_family == AF_INET6)
00389     {
00390         palIpV6Addr_t ipV6Addr;
00391         struct sockaddr_in6* ip6addr = (struct sockaddr_in6*)input;
00392         memcpy(ipV6Addr, &ip6addr->sin6_addr, PAL_IPV6_ADDRESS_SIZE);
00393         result = pal_setSockAddrIPV6Addr(out, ipV6Addr);
00394         if (result == PAL_SUCCESS)
00395         {
00396             result = pal_setSockAddrPort(out, PAL_NTOHS(ip6addr->sin6_port));
00397         }
00398         *length = sizeof(struct sockaddr_in6);
00399     }
00400     else
00401     { // we got unspeicified in one of the tests, so Don't fail , but don't translate address.
00402         //result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
00403     }
00404 
00405     return result;
00406 }
00407 
00408 palStatus_t pal_plat_socketsInit(void* context)
00409 {
00410     PAL_UNUSED_ARG(context);
00411     palStatus_t result = PAL_SUCCESS;
00412 
00413     if (s_pal_network_initialized == 1)
00414     {
00415         return PAL_SUCCESS; // already initialized.
00416     }
00417 
00418 
00419 #if PAL_NET_ASYNCHRONOUS_SOCKET_API
00420     pthread_attr_t attr;
00421     int res;
00422 
00423     result = pal_osMutexCreate(&s_mutexSocketCallbacks);
00424     if (result != PAL_SUCCESS)
00425     {
00426         return result;
00427     }
00428 
00429     result = pal_osMutexCreate(&s_mutexSocketEventFilter);
00430     if (PAL_SUCCESS != result)
00431     {
00432         return result;
00433     }
00434 
00435 
00436     result = pal_osSemaphoreCreate(0, &s_socketCallbackSignalSemaphore);
00437     if (result != PAL_SUCCESS)
00438     {
00439         // todo: clean up the mess created so far
00440         return result;
00441     }
00442 
00443     // Sleep at first wait
00444     result = pal_osSemaphoreCreate(0, &s_socketCallbackSemaphore);
00445     if (result != PAL_SUCCESS)
00446     {
00447         if (pal_osMutexDelete(&s_mutexSocketCallbacks) != PAL_SUCCESS) //cleanup allocated resources
00448         {
00449             // TODO print error using logging mechanism when available.
00450         }
00451         return result;
00452     }
00453     // prepare thread attributes
00454     pthread_attr_init(&attr);
00455     pthread_attr_setstacksize (&attr, PAL_NET_TEST_ASYNC_SOCKET_MANAGER_THREAD_STACK_SIZE);  //sets the minimum stack size
00456     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00457 
00458     // create the thread
00459     res = pthread_create(&s_pollThread, &attr, &asyncSocketManager, 0);
00460     if (res < 0)
00461     {
00462         result = translateErrorToPALError(res);
00463     }
00464     else
00465     {
00466         // Wait here for the thread to be initialized.
00467         result = pal_osSemaphoreWait(s_socketCallbackSemaphore, PAL_RTOS_WAIT_FOREVER, NULL);
00468         if (PAL_SUCCESS != result)
00469         {
00470             goto end;
00471         }
00472         result = pal_osSemaphoreDelete(&s_socketCallbackSemaphore);
00473         if (PAL_SUCCESS != result)
00474         {
00475             goto end;
00476         }
00477     }
00478 #endif
00479 
00480 end:
00481     if (PAL_SUCCESS == result)
00482     {
00483         s_pal_network_initialized = 1;
00484     }
00485 
00486 #if PAL_NET_ASYNCHRONOUS_SOCKET_API
00487     pthread_attr_destroy(&attr);
00488 #endif
00489 
00490     return result;
00491 }
00492 
00493 palStatus_t pal_plat_registerNetworkInterface (void* context, uint32_t* interfaceIndex)
00494 {
00495     palStatus_t result = PAL_SUCCESS;
00496     uint32_t index = 0;
00497     bool found = false;
00498 
00499     for (index = 0; index < s_palNumOfInterfaces; index++) // if specific context already registered return existing index instead of registering again.
00500     {
00501         if (memcmp(s_palNetworkInterfacesSupported[index].interfaceName, (const char *)context, strlen(s_palNetworkInterfacesSupported[index].interfaceName)) == 0)
00502         {
00503             found = true;
00504             *interfaceIndex = index;
00505             break;
00506         }
00507     }
00508     if (false == found)
00509     {
00510         if (s_palNumOfInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES)
00511         {
00512             strncpy(s_palNetworkInterfacesSupported[s_palNumOfInterfaces].interfaceName, (const char *)context, PAL_NET_MAX_IF_NAME_LENGTH-1);
00513             s_palNetworkInterfacesSupported[s_palNumOfInterfaces].interfaceName[PAL_NET_MAX_IF_NAME_LENGTH-1] = '\0';
00514             *interfaceIndex = s_palNumOfInterfaces;
00515             ++s_palNumOfInterfaces;
00516         }
00517         else
00518         {
00519             result = PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED ;
00520         }
00521     }
00522 
00523     return result;
00524 }
00525 
00526 palStatus_t pal_plat_socketsTerminate (void* context)
00527 {
00528     PAL_UNUSED_ARG(context);
00529     palStatus_t result = PAL_SUCCESS;
00530     palStatus_t firstError = PAL_SUCCESS;
00531 
00532 #if PAL_NET_ASYNCHRONOUS_SOCKET_API
00533     // Critical section to update globals
00534     result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
00535     if (result != PAL_SUCCESS)
00536     {
00537         // TODO print error using logging mechanism when available.
00538         firstError = result;
00539     }
00540 
00541     s_nfds = PAL_SOCKETS_TERMINATE;
00542     result = pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore);
00543     if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
00544     {
00545         // TODO print error using logging mechanism when available.
00546         firstError = result;
00547     }
00548     // Tell the poll thread to interrupt so that it can check for termination.
00549     pthread_kill(s_pollThread, SIGUSR1);
00550     result = pal_osMutexRelease(s_mutexSocketCallbacks);
00551     if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
00552     {
00553         // TODO print error using logging mechanism when available.
00554         firstError = result;
00555     }
00556 
00557     pthread_join(s_pollThread, NULL);
00558 
00559     result = pal_osSemaphoreDelete(&s_socketCallbackSignalSemaphore);
00560     if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
00561     {
00562         // TODO print error using logging mechanism when available.
00563         firstError = result;
00564     }
00565 
00566     result = pal_osMutexDelete(&s_mutexSocketEventFilter);
00567     if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
00568     {
00569         // TODO print error using logging mechanism when available.
00570         firstError = result;
00571     }
00572 
00573     result = pal_osMutexDelete(&s_mutexSocketCallbacks);
00574     if ((PAL_SUCCESS != result ) && (PAL_SUCCESS == firstError))
00575     {
00576         // TODO print error using logging mechanism when available.
00577         firstError = result;
00578     }
00579 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
00580 
00581     s_pal_network_initialized = 0;
00582 
00583     return firstError;
00584 }
00585 
00586 /*
00587  * NOTE!!!!
00588  * When creating socket in Linux, we ignore interfaceNum provided.
00589  * The socket should be bound to interface pal_plat_bind API (bind to address reflects the bound between
00590  * socket and interface).
00591  */
00592 palStatus_t pal_plat_socket (palSocketDomain_t  domain, palSocketType_t  type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* sockt)
00593 {
00594     int result = PAL_SUCCESS;
00595     int sockfd;
00596     int sockBehavior = 0;
00597 
00598     if (interfaceNum >= s_palNumOfInterfaces && PAL_NET_DEFAULT_INTERFACE != interfaceNum)
00599     {
00600         return PAL_ERR_INVALID_ARGUMENT ;
00601     }
00602 
00603     // These are the same in Linux
00604     if(type == PAL_SOCK_STREAM_SERVER )
00605     {
00606         type = PAL_SOCK_STREAM;
00607     }
00608 
00609     // Compile time check that PAL values are the same as Linux values
00610     PAL_ASSERT_STATIC(AF_INET == PAL_AF_INET);
00611     PAL_ASSERT_STATIC(AF_INET6 == PAL_AF_INET6 );
00612     PAL_ASSERT_STATIC(AF_UNSPEC == PAL_AF_UNSPEC);
00613     PAL_ASSERT_STATIC(SOCK_DGRAM == (unsigned int)PAL_SOCK_DGRAM );
00614     PAL_ASSERT_STATIC(SOCK_STREAM == (unsigned int)PAL_SOCK_STREAM);
00615 
00616     if (nonBlockingSocket)
00617     {
00618         sockBehavior = SOCK_NONBLOCK;
00619     }
00620 
00621     // SOCK_NONBLOCK since Linux 2.6.27
00622     sockfd = socket(domain, type | sockBehavior , 0);
00623     // Note - though it is not an error, if we get sockfd == 0 then we probably (accidentally closed fd 0 somewhere else)
00624     if (sockfd == PAL_LINUX_INVALID_SOCKET)
00625     {
00626         result = translateErrorToPALError(errno);
00627     }
00628     else
00629     {
00630         *sockt = (palSocket_t )sockfd;
00631     }
00632     return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
00633 }
00634 
00635 
00636 palStatus_t pal_plat_getSocketOptions (palSocket_t socket, palSocketOptionName_t  optionName, void* optionValue, palSocketLength_t* optionLength)
00637 {
00638     int result = PAL_SUCCESS;
00639     int linuxName;
00640 
00641     // TODO moved to shared function
00642     switch ((palSocketOptionName_t )optionName)
00643     {
00644     case PAL_SO_SNDTIMEO :
00645         linuxName = SO_SNDTIMEO ;
00646         break;
00647     case PAL_SO_RCVTIMEO :
00648         linuxName = SO_RCVTIMEO ;
00649         break;
00650 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
00651     case PAL_SO_KEEPALIVE :
00652         linuxName = SO_KEEPALIVE;
00653         break;
00654     case PAL_SO_KEEPIDLE :
00655         linuxName = TCP_KEEPIDLE;
00656         break;
00657     case PAL_SO_KEEPINTVL :
00658         linuxName = TCP_KEEPINTVL;
00659         break;
00660 #endif
00661     case PAL_SO_REUSEADDR:
00662         linuxName = SO_REUSEADDR;
00663         break;
00664     default:
00665         // Unsupported option
00666         result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED ;
00667     }
00668 
00669     if (result == PAL_SUCCESS)
00670     {
00671         if (PAL_SO_REUSEADDR == optionName ||
00672             PAL_SO_SNDTIMEO  == optionName ||
00673             PAL_SO_RCVTIMEO  == optionName)
00674         {
00675             result = getsockopt ((int)socket, SOL_SOCKET, linuxName, optionValue, optionLength);
00676         }
00677 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
00678         else if (PAL_SO_KEEPALIVE  == optionName)
00679         {
00680             result = getsockopt((int)socket, SOL_SOCKET, linuxName, optionValue, optionLength);
00681         }
00682         else
00683         {
00684             result = getsockopt((int)socket, SOL_TCP, linuxName, optionValue, optionLength);
00685         }
00686 #endif
00687 
00688         if(result == -1)
00689         {
00690             result = translateErrorToPALError(errno);
00691         }
00692     }
00693 
00694     return result;
00695 }
00696 
00697 // Assume input timeout value is in milliseconds.
00698 palStatus_t pal_plat_setSocketOptions (palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength)
00699 {
00700     int result = PAL_SUCCESS;
00701     int linuxName;
00702     PAL_UNUSED_ARG(optionLength);
00703 
00704 
00705     struct timeval timeout;
00706     timeout.tv_sec =  0;
00707     timeout.tv_usec = 0;
00708 
00709     switch (optionName)
00710     {
00711     case PAL_SO_SNDTIMEO :
00712         linuxName = SO_SNDTIMEO;
00713         timeout.tv_sec = (*(int *)optionValue)/1000 ;
00714         timeout.tv_usec = ((*(int *)optionValue)%1000)*1000 ;
00715         break;
00716     case PAL_SO_RCVTIMEO :
00717         linuxName = SO_RCVTIMEO;
00718         timeout.tv_sec = (*(int *)optionValue)/1000 ;
00719         timeout.tv_usec = ((*(int *)optionValue)%1000)*1000 ;
00720         break;
00721 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
00722     case PAL_SO_KEEPALIVE :
00723         linuxName = SO_KEEPALIVE;
00724         break;
00725     case PAL_SO_KEEPIDLE :
00726         linuxName = TCP_KEEPIDLE;
00727         break;
00728     case PAL_SO_KEEPINTVL :
00729         linuxName = TCP_KEEPINTVL;
00730         break;
00731 #endif
00732     case PAL_SO_REUSEADDR:
00733         linuxName = SO_REUSEADDR;
00734         break;
00735     default:
00736         // Unsupported option
00737         result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED ;
00738     }
00739 
00740     if (PAL_SUCCESS == result)
00741     {
00742         if (PAL_SO_SNDTIMEO  == optionName || PAL_SO_RCVTIMEO  == optionName)
00743         {
00744             result = setsockopt ((int)socket, SOL_SOCKET, linuxName, &timeout, sizeof(timeout));
00745         }
00746 #ifdef PAL_NET_TCP_AND_TLS_SUPPORT
00747         else if (PAL_SO_KEEPIDLE  == optionName || PAL_SO_KEEPINTVL  == optionName)
00748         {
00749             result = setsockopt ((int)socket, SOL_TCP, linuxName, (int *)optionValue, optionLength);
00750         }
00751 #endif
00752         else
00753         {
00754             result = setsockopt ((int)socket, SOL_SOCKET, linuxName, (int *)optionValue, optionLength);
00755         }
00756 
00757         if(-1 == result)
00758         {
00759             result = translateErrorToPALError(errno);
00760         }
00761     }
00762 
00763     return result;
00764 }
00765 
00766 palStatus_t pal_plat_isNonBlocking (palSocket_t socket, bool* isNonBlocking)
00767 {
00768     int flags = fcntl((int)socket, F_GETFL);
00769 
00770     if (0 != (flags & O_NONBLOCK))
00771     {
00772         *isNonBlocking = true;
00773     }
00774     else
00775     {
00776         *isNonBlocking = false;
00777     }
00778     return PAL_SUCCESS;
00779 }
00780 
00781 
00782 palStatus_t pal_plat_bind (palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength)
00783 {
00784     int result = PAL_SUCCESS;
00785     int res = 0;
00786     struct sockaddr_storage internalAddr = {0} ;
00787 
00788     result = pal_plat_SockAddrToSocketAddress(myAddress, (struct sockaddr *)&internalAddr);
00789     if (result == PAL_SUCCESS)
00790     {
00791         res = bind((int)socket, (struct sockaddr *)&internalAddr, addressLength);
00792         if (res == -1)
00793         {
00794             result = translateErrorToPALError(errno);
00795         }
00796     }
00797 
00798     return result;
00799 }
00800 
00801 
00802 palStatus_t pal_plat_receiveFrom (palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived)
00803 {
00804     palStatus_t result = PAL_SUCCESS;
00805     ssize_t res;
00806     struct sockaddr_storage internalAddr;
00807     socklen_t addrlen;
00808 
00809     clearSocketFilter((int)socket);
00810     addrlen = sizeof(struct sockaddr_storage);
00811     res = recvfrom((int)socket, buffer, length, 0 ,(struct sockaddr *)&internalAddr, &addrlen);
00812     if(res == -1)
00813     {
00814         result = translateErrorToPALError(errno);
00815     }
00816     else // only return address / bytesReceived in case of success
00817     {
00818         if ((NULL != from) && (NULL != fromLength))
00819         {
00820             result = pal_plat_socketAddressToPalSockAddr((struct sockaddr *)&internalAddr, from, fromLength);
00821         }
00822         *bytesReceived = res;
00823     }
00824 
00825     return result;
00826 }
00827 
00828 palStatus_t pal_plat_sendTo (palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent)
00829 {
00830     palStatus_t result = PAL_SUCCESS;
00831     ssize_t res;
00832 
00833     clearSocketFilter((int)socket);
00834     res = sendto((int)socket, buffer, length, 0, (struct sockaddr *)to, toLength);
00835     if(res == -1)
00836     {
00837         result = translateErrorToPALError(errno);
00838     }
00839     else
00840     {
00841         *bytesSent = res;
00842     }
00843 
00844     return result;
00845 }
00846 
00847 palStatus_t pal_plat_close (palSocket_t* socket)
00848 {
00849     palStatus_t result = PAL_SUCCESS;
00850     int res;
00851     unsigned int i,j;
00852 
00853     if  (*socket == (void *)PAL_LINUX_INVALID_SOCKET) // socket already closed - return success.
00854     {
00855         PAL_LOG(DBG, "socket close called on socket which was already closed");
00856         return result;
00857     }
00858 #if PAL_NET_ASYNCHRONOUS_SOCKET_API
00859     // Critical section to update globals
00860     result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
00861     if (result != PAL_SUCCESS)
00862     {
00863         // TODO print error using logging mechanism when available.
00864         return result;
00865     }
00866 
00867     for(i= 0 ; i < s_nfds; i++)
00868     {
00869         // check if we have we found the socket being closed
00870         if (s_fds[i].fd == (int)*socket)
00871         {
00872             // Remove from async socket list
00873             // Close the gap in the socket data structures.
00874             for(j = i; j < s_nfds - 1; j++)
00875             {
00876                 s_fds[j].fd = s_fds[j+1].fd;
00877                 s_fds[j].events = s_fds[j+1].events;
00878                 s_callbacks[j] = s_callbacks[j+1];
00879                 s_callbackArgs[j] = s_callbackArgs[j+1];
00880             }
00881             // Blank out the last one
00882             s_fds[j].fd = 0;
00883             s_callbacks[j] = 0;
00884             s_callbackArgs[j] = 0;
00885             s_nfds--;
00886             // Tell the poll thread to remove the socket
00887             pthread_kill(s_pollThread, SIGUSR1);
00888             break;
00889         }
00890     }
00891     result = pal_osMutexRelease(s_mutexSocketCallbacks);
00892     if (result != PAL_SUCCESS)
00893     {
00894         // TODO print error using logging mechanism when available.
00895         return result;
00896     }
00897 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
00898     // In Linux it is ok to close a socket while it is being polled, but may not be on other os's
00899     res = close((int) *socket);
00900     if(res == -1)
00901         result = translateErrorToPALError(errno);
00902     else
00903     {
00904         *socket = (void *)PAL_LINUX_INVALID_SOCKET;
00905     }
00906     return result;
00907 }
00908 
00909 palStatus_t pal_plat_getNumberOfNetInterfaces ( uint32_t* numInterfaces)
00910 {
00911     *numInterfaces =  s_palNumOfInterfaces;
00912     return PAL_SUCCESS;
00913 }
00914 
00915 palStatus_t pal_plat_getNetInterfaceInfo (uint32_t interfaceNum, palNetInterfaceInfo_t  * interfaceInfo)
00916 {
00917     palStatus_t result = PAL_SUCCESS;
00918     struct ifaddrs *ifap,*ifa;
00919     int res,n;
00920     uint32_t found = 0;
00921 
00922     if (interfaceNum >= s_palNumOfInterfaces)
00923     {
00924         return PAL_ERR_INVALID_ARGUMENT ;
00925     }
00926 
00927     res = getifaddrs(&ifap);
00928     if(res < 0)
00929     {
00930         result = translateErrorToPALError(errno);
00931     }
00932     else
00933     {
00934         for (ifa = ifap, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++)
00935         {
00936             if (ifa->ifa_addr == NULL)
00937                 continue;
00938             int family = ifa->ifa_addr->sa_family;
00939             if (strcmp(s_palNetworkInterfacesSupported[interfaceNum].interfaceName, ifa->ifa_name) == 0)
00940             {
00941                 if (family == AF_INET || family == AF_INET6)
00942                 {
00943                     found = 1;
00944                     if (family == AF_INET)
00945                     {
00946                         interfaceInfo->addressSize = sizeof(struct sockaddr_in);
00947                     }
00948                     else
00949                     {
00950                         interfaceInfo->addressSize = sizeof(struct sockaddr_in6);
00951                     }
00952 
00953                     strncpy(interfaceInfo->interfaceName, s_palNetworkInterfacesSupported[interfaceNum].interfaceName, strlen(s_palNetworkInterfacesSupported[interfaceNum].interfaceName));
00954 
00955                     result = pal_plat_socketAddressToPalSockAddr(ifa->ifa_addr, &interfaceInfo->address, &interfaceInfo->addressSize);
00956 
00957                     break;
00958                 }
00959             }
00960         }
00961         // free what was allocated by getifaddrs
00962         freeifaddrs(ifap);
00963     }
00964 
00965     //interface not found error
00966     if (found != 1 && result == PAL_SUCCESS)
00967     {
00968         PAL_LOG(ERR, "Network failed reading interface info");
00969         result = PAL_ERR_GENERIC_FAILURE;
00970     }
00971 
00972     return result;
00973 }
00974 
00975 
00976 palStatus_t pal_plat_socketMiniSelect (const palSocket_t socketsToCheck[PAL_NET_SOCKET_SELECT_MAX_SOCKETS], uint32_t numberOfSockets, pal_timeVal_t* timeout,
00977     uint8_t palSocketStatus[PAL_NET_SOCKET_SELECT_MAX_SOCKETS], uint32_t * numberOfSocketsSet)
00978 {
00979         uint32_t index = 0;
00980         palStatus_t result = PAL_SUCCESS;
00981         fd_set readset, writeset, exset;
00982         // Keep a local copy because select in Linux will modify it.
00983         struct timeval tmpTimeout;
00984         int res;
00985         int fd;
00986         int maxfd = 0;
00987 
00988         if ((NULL == socketsToCheck) || (NULL == numberOfSocketsSet) || (NULL == timeout))
00989         {
00990             return PAL_ERR_INVALID_ARGUMENT ;
00991         }
00992 
00993         // Copy the values manually as the struct variables may have different sizes.
00994         tmpTimeout.tv_sec = timeout->pal_tv_sec;
00995         tmpTimeout.tv_usec = timeout->pal_tv_usec;
00996 
00997         *numberOfSocketsSet = 0;
00998 
00999         FD_ZERO(&readset);
01000         FD_ZERO(&writeset);
01001         FD_ZERO(&exset);
01002 
01003         for(index = 0; index < numberOfSockets; index++)
01004         {
01005             fd = (int)socketsToCheck[index];
01006             FD_SET(fd, &readset);
01007             // Do not detect writes because they will not block unless something is in the process of being written(Nir)
01008             // XXX: Actually for a nonblocking connect() we need to detect readiness for write
01009             // to find out if the socket is ready.
01010             FD_SET(fd, &writeset);
01011             FD_SET(fd, &exset);
01012             if (fd > maxfd)
01013             {
01014                  maxfd = fd;
01015             }
01016         }
01017 
01018         res = select(maxfd + 1, &readset, &writeset, &exset, &tmpTimeout);
01019         if(res == -1)
01020         {
01021             result = translateErrorToPALError(errno);
01022         }
01023         else if (res > 0) // select returns 0 in case timeout expire
01024         {
01025             for(index = 0; index < numberOfSockets; index++)
01026             {
01027                 uint8_t socketStatus = 0;
01028                 fd = (int)socketsToCheck[index];
01029 
01030                 if(FD_ISSET(fd, &readset))
01031                 {
01032                     socketStatus |= PAL_NET_SOCKET_SELECT_RX_BIT;
01033                 }
01034                 if(FD_ISSET(fd, &writeset))
01035                 {
01036                     socketStatus |= PAL_NET_SOCKET_SELECT_TX_BIT;
01037                 }
01038                 if(FD_ISSET(fd, &exset))
01039                 {
01040                     socketStatus |= PAL_NET_SOCKET_SELECT_ERR_BIT;
01041                 }
01042 
01043                 palSocketStatus[index] = socketStatus;
01044             }
01045             *numberOfSocketsSet = res;
01046         }
01047 
01048         return result ;
01049 }
01050 
01051 #if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
01052 palStatus_t pal_plat_listen (palSocket_t socket, int backlog)
01053 {
01054     palStatus_t result = PAL_SUCCESS;
01055     int res;
01056 
01057     res = listen((int)socket,backlog);
01058     if(res == -1)
01059     {
01060         result = translateErrorToPALError(errno);
01061     }
01062     return result;
01063 }
01064 
01065 
01066 palStatus_t pal_plat_accept (palSocket_t socket, palSocketAddress_t * address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket)
01067 {
01068     int res = 0;
01069     palStatus_t result = PAL_SUCCESS;
01070     struct sockaddr_storage internalAddr = {0} ;
01071 
01072     res = accept((int)socket,(struct sockaddr *)&internalAddr, addressLen);
01073     if(res == -1)
01074     {
01075         result = translateErrorToPALError(errno);
01076     }
01077     else
01078     {
01079         *acceptedSocket = (palSocket_t*)res;
01080         result = pal_plat_socketAddressToPalSockAddr((struct sockaddr *)&internalAddr, address, addressLen);
01081     }
01082 
01083     return result;
01084 }
01085 
01086 
01087 palStatus_t pal_plat_connect (palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen)
01088 {
01089     int result = PAL_SUCCESS;
01090     int res;
01091     struct sockaddr_storage internalAddr = {0} ;
01092 
01093     result = pal_plat_SockAddrToSocketAddress(address, (struct sockaddr *)&internalAddr);
01094     if (result == PAL_SUCCESS)
01095     {
01096         res = connect((int)socket,(struct sockaddr *)&internalAddr, addressLen);
01097         if(res == -1)
01098         {
01099             result = translateErrorToPALError(errno);
01100         }
01101     }
01102 
01103     return result;
01104 }
01105 
01106 palStatus_t pal_plat_recv (palSocket_t socket, void *buffer, size_t len, size_t* recievedDataSize)
01107 {
01108     palStatus_t result = PAL_SUCCESS;
01109     ssize_t res;
01110 
01111     clearSocketFilter((int)socket);
01112     res = recv((int)socket, buffer, len, 0);
01113     if(res ==  -1)
01114     {
01115         result = translateErrorToPALError(errno);
01116     }
01117     else
01118     {
01119         if (0 == res)
01120         {
01121             result = PAL_ERR_SOCKET_CONNECTION_CLOSED ;
01122         }
01123         *recievedDataSize = res;
01124     }
01125     return result;
01126 }
01127 
01128 palStatus_t pal_plat_send (palSocket_t socket, const void *buf, size_t len, size_t *sentDataSize)
01129 {
01130     palStatus_t result = PAL_SUCCESS;
01131     ssize_t res;
01132 
01133     clearSocketFilter((int)socket);
01134 
01135     res = send((int)socket, buf, len, 0);
01136     if(res == -1)
01137     {
01138         result = translateErrorToPALError(errno);
01139     }
01140     else
01141     {
01142         *sentDataSize = res;
01143     }
01144 
01145     return result;
01146 }
01147 
01148 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
01149 
01150 
01151 
01152 
01153 
01154 
01155 
01156 #if PAL_NET_ASYNCHRONOUS_SOCKET_API
01157 palStatus_t pal_plat_asynchronousSocket (palSocketDomain_t  domain, palSocketType_t  type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t  callback, void* callbackArgument, palSocket_t* socket)
01158 {
01159 
01160     int err;
01161     int flags;
01162     palStatus_t result = pal_plat_socket (domain,  type,  nonBlockingSocket,  interfaceNum, socket);
01163 
01164 
01165 
01166         // initialize the socket to be ASYNC so we get SIGIO's for it
01167         // XXX: this needs to be conditionalized as the blocking IO might have some use also.
01168         err = fcntl((int)*socket, F_SETOWN, getpid());
01169         assert(err != -1);
01170 
01171         flags = fcntl((int)*socket, F_GETFL, 0);
01172         assert(flags >= 0);
01173 
01174         flags |= O_ASYNC;
01175 
01176         err = fcntl((int)*socket, F_SETFL, flags);
01177 
01178         if (err == -1)
01179         {
01180             result = translateErrorToPALError(errno);
01181         }
01182 
01183 
01184     if (result == PAL_SUCCESS)
01185     {
01186         // Critical section to update globals
01187         result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
01188         if (result != PAL_SUCCESS)
01189         {
01190             // TODO print error using logging mechanism when available.
01191             return result;
01192         }
01193         s_fds[s_nfds].fd = (int)*socket;
01194         s_fds[s_nfds].events = POLLIN|POLLERR;  //TODO POLLOUT missing is not documented
01195         s_callbacks[s_nfds] = callback;
01196         s_callbackArgs[s_nfds] = callbackArgument;
01197         s_nfds++;
01198         result = pal_osMutexRelease(s_mutexSocketCallbacks);
01199         if (result != PAL_SUCCESS)
01200         {
01201             // TODO print error using logging mechanism when available.
01202             return result;
01203         }
01204         // Tell the poll thread to add the new socket
01205         pthread_kill(s_pollThread, SIGUSR1);
01206     }
01207 
01208     return result;
01209 
01210 }
01211 
01212 #endif
01213 
01214 #if PAL_NET_DNS_SUPPORT
01215 
01216 palStatus_t pal_plat_getAddressInfo (const char *url, palSocketAddress_t *address, palSocketLength_t* length)
01217 {
01218     palStatus_t result = PAL_SUCCESS;
01219     palSocketAddress_t localAddress = {0};
01220     palSocketAddress_t zeroAddress = {0};
01221     struct addrinfo *pAddrInf = NULL;
01222     struct addrinfo hints = {0};
01223     int res;
01224     int supportedAddressType1 = 0;
01225     int supportedAddressType2 = 0;
01226     hints.ai_family = AF_UNSPEC;
01227 
01228 #if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY
01229     supportedAddressType1 = AF_INET;
01230     supportedAddressType2 = AF_INET6;
01231     hints.ai_family = AF_UNSPEC;
01232 #elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY
01233     supportedAddressType1 = AF_INET;
01234     supportedAddressType2 = AF_INET;
01235     hints.ai_family = AF_INET;
01236 #elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY
01237     supportedAddressType1 = AF_INET6;
01238     supportedAddressType2 = AF_INET6;
01239     hints.ai_family = AF_INET6;
01240 #else
01241 #error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value.
01242 #endif
01243 
01244     res = getaddrinfo(url, NULL, &hints, &pAddrInf);
01245     if(res < 0)
01246     {
01247         result = translateErrorToPALError(errno);
01248     }
01249     else
01250     {
01251         if ((pAddrInf != NULL) && (pAddrInf->ai_family == supportedAddressType1 || pAddrInf->ai_family == supportedAddressType2))
01252         {
01253             result = pal_plat_socketAddressToPalSockAddr((struct sockaddr*)pAddrInf->ai_addr, &localAddress, length);
01254 
01255             if (0 == memcmp(localAddress.addressData, zeroAddress.addressData, PAL_NET_MAX_ADDR_SIZE) ) // invalid 0 address
01256             {
01257                 result = PAL_ERR_SOCKET_DNS_ERROR ;
01258             }
01259             else
01260             {
01261                 *address = localAddress;
01262             }
01263         }
01264         else
01265         {
01266             result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY ;
01267         }
01268 
01269         freeaddrinfo(pAddrInf);
01270     }
01271 
01272     return result;
01273 }
01274 
01275 #endif