Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_plat_network.cpp Source File

pal_plat_network.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 
00018 #include "pal.h"
00019 #include "pal_plat_network.h"
00020 
00021 #include "mbed.h"
00022 
00023 typedef void(*palSelectCallbackFunction_t)();
00024 
00025 #if defined (__CC_ARM) || defined(__IAR_SYSTEMS_ICC__)
00026 
00027 void palSelectCallbackNull(void* arg)
00028 {
00029 }
00030 
00031 #define NULL_FUNCTION palSelectCallbackNull
00032 
00033 
00034 #elif defined (__GNUC__)
00035 
00036 #define NULL_FUNCTION NULL
00037 
00038 #endif
00039 
00040 
00041 #define PAL_SOCKET_OPTION_ERROR (-1)
00042 
00043 
00044 typedef enum {
00045     PAL_PLAT_SOCKET_NOT_CONNECTED = 0,
00046     PAL_PLAT_SOCKET_CONNECTING = 1,
00047     PAL_PLAT_SOCKET_CONNECTED = 2
00048 
00049 } palConnectState;
00050 
00051 
00052 void palConnectCallBack()
00053 {
00054 }
00055 
00056         class PALSocketWrapper
00057         {
00058         public:
00059             PALSocketWrapper() : initialized(false), activeSocket(NULL), isNonBlockingOnCreation(false), callbackFunction(NULL_FUNCTION), callbackArgument(NULL), selectCallbackFunction(NULL), connectState(PAL_PLAT_SOCKET_NOT_CONNECTED), socketTypeVal(PAL_SOCK_DGRAM ), attachCallbackObject(NULL), rxBuffer(0), rxBufferSet(false)
00060         {
00061 
00062             }
00063             nsapi_error_t initialize(Socket* socket, palSocketType_t  socketType,bool isNonBlocking, palAsyncSocketCallback_t  callback, void* argument);
00064             palAsyncSocketCallback_t  getCallback( ) const;
00065             void* getCallbackArgument() const ;
00066             bool isNonBlocking() const ;
00067             bool isConnected() const ;
00068             void attachCallback();
00069             Socket* getActiveSocket();
00070             palSocketType_t  getSocketType() const;
00071             char getAndResetRxBuffer();
00072             bool isRxBufferSet() const;
00073             palStatus_t setRxBuffer(char data);
00074             void updateCallback(/*palAsyncSocketCallback_t callback, void* argument,*/ palSelectCallbackFunction_t selectCallback);
00075             virtual ~PALSocketWrapper()
00076             {
00077                 if (NULL != activeSocket  )
00078                 {
00079                     activeSocket->close();
00080                     delete activeSocket;
00081                 }
00082             }
00083 
00084             // nsapi socket funcitons exposed:
00085             nsapi_error_t close();
00086             nsapi_error_t bind(const SocketAddress &address);
00087             void set_blocking(bool blocking);
00088             void set_timeout(int timeout);
00089             nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen);
00090             nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen);
00091             void attach(mbed::Callback<void()> func);
00092             //void sigio(mbed::Callback<void()> func); // switch attach to sigio for verison 5.4
00093             // nsapi UDP socket funcitons exposed:
00094             nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size);
00095             nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size);
00096             //nsapi TCP socket funcitons exposed:
00097             nsapi_error_t connect(const SocketAddress &address);
00098             nsapi_size_or_error_t send(const void *data, nsapi_size_t size);
00099             nsapi_size_or_error_t recv(void *data, nsapi_size_t size);
00100             //nsapi TCP server socket funcitons exposed:
00101             nsapi_error_t listen(int backlog = 1);
00102             nsapi_error_t accept(TCPSocket *connection, SocketAddress *address = NULL);
00103 
00104 
00105         private:
00106             bool initialized;
00107             Socket* activeSocket;
00108             bool isNonBlockingOnCreation;
00109             palAsyncSocketCallback_t  callbackFunction;
00110             void* callbackArgument;
00111             palSelectCallbackFunction_t selectCallbackFunction;
00112             palConnectState connectState;
00113             palSocketType_t  socketTypeVal;
00114             Callback<void()> attachCallbackObject;
00115             events::EventQueue* shared_event_queue;
00116             char rxBuffer;
00117             bool rxBufferSet;
00118         };
00119 
00120         void PALSocketWrapper::updateCallback( palSelectCallbackFunction_t selectCallback )
00121         {
00122             bool shouldSetCallback = false;
00123             if ((NULL == selectCallbackFunction) && (NULL == callbackFunction)) //callback already set - no need to set again
00124             {
00125                 shouldSetCallback = true;
00126             }
00127 
00128             selectCallbackFunction = selectCallback;
00129 
00130             if ((NULL != selectCallbackFunction) || (NULL != callbackFunction))
00131             {
00132                 if (shouldSetCallback)
00133                 {
00134                     Callback<void()> mycall(this, &PALSocketWrapper::attachCallback);
00135                     activeSocket->sigio(mycall);
00136                 }
00137             }
00138             else
00139             {
00140                 activeSocket->sigio(NULL);
00141             }
00142         }
00143 
00144         Socket* PALSocketWrapper::getActiveSocket()
00145         {
00146             return activeSocket;
00147         }
00148 
00149         char PALSocketWrapper::getAndResetRxBuffer()
00150         {
00151             rxBufferSet = false;
00152             return rxBuffer;
00153         }
00154 
00155         bool PALSocketWrapper::isRxBufferSet() const
00156         {
00157             return rxBufferSet;
00158         }
00159 
00160         palStatus_t PALSocketWrapper::setRxBuffer( char data)
00161         {
00162             PAL_VALIDATE_CONDITION_WITH_ERROR((true == rxBufferSet), PAL_ERR_SOCKET_GENERIC );
00163 
00164             rxBuffer = data;
00165             rxBufferSet = true;
00166 
00167             return PAL_SUCCESS;
00168         }
00169 
00170         palAsyncSocketCallback_t  PALSocketWrapper::getCallback() const
00171         {
00172             return callbackFunction;
00173         }
00174 
00175         palSocketType_t   PALSocketWrapper::getSocketType() const
00176         {
00177             return socketTypeVal;
00178         }
00179 
00180 
00181         void * PALSocketWrapper::getCallbackArgument() const
00182         {
00183             return callbackArgument;
00184         }
00185 
00186         bool PALSocketWrapper::isNonBlocking() const
00187         {
00188             return isNonBlockingOnCreation;
00189         }
00190 
00191         bool PALSocketWrapper::isConnected() const
00192         {
00193             return ((PAL_PLAT_SOCKET_CONNECTED == connectState) && (PAL_SOCK_STREAM == socketTypeVal));
00194         }
00195 
00196         void PALSocketWrapper::attachCallback()
00197         {
00198             if (NULL != callbackFunction)
00199             {
00200                 // Since the socket callback may be called from interrupt context, depending on the
00201                 // network interface used, we need to debounce the client callback to happen from
00202                 // a thread context to keep client side implementation platform agnostic.
00203                 assert(shared_event_queue);
00204                 shared_event_queue->call(callbackFunction, callbackArgument);
00205             }
00206             if (NULL != selectCallbackFunction)
00207             {
00208                 // Note: this is not tested yet
00209                 assert(shared_event_queue);
00210                 shared_event_queue->call(selectCallbackFunction);
00211             }
00212             if (PAL_PLAT_SOCKET_CONNECTING == connectState)
00213             {
00214                 connectState = PAL_PLAT_SOCKET_CONNECTED;// if we got a callback while connecting assume we are connected
00215                 if (palConnectCallBack == selectCallbackFunction)
00216                 {
00217                     selectCallbackFunction = NULL;
00218                 }
00219             }
00220         }
00221 
00222         nsapi_error_t  PALSocketWrapper::initialize(Socket* socket, palSocketType_t  socketType, bool isNonBlocking, palAsyncSocketCallback_t  callback, void* argument)
00223         {
00224         // check that we got a valid socket and the socket type is supported
00225             PAL_VALIDATE_CONDITION_WITH_ERROR(((true == initialized) || (NULL == socket) || 
00226                                               ((socketType != PAL_SOCK_STREAM) && (socketType != PAL_SOCK_STREAM_SERVER ) && 
00227                                                (socketType != PAL_SOCK_DGRAM ))),NSAPI_ERROR_PARAMETER);
00228 
00229 
00230             // Pre fetch and store the shared queue used for bouncing the callbacks out of interrupt
00231             // context, as the user of it may be ran from interrupt and it can't go and start
00232             // creating worker threads from there.
00233             // Note: the code uses mbed_highprio_event_queue() instead of mbed_event_queue()
00234             // as the high priority queue and its thread is likely there already thanks to
00235             // arm_hal_timer.cpp. Technically the client side does not really care, if the events
00236             // were delayed a bit by other events or not.
00237             shared_event_queue = mbed_highprio_event_queue();
00238             PAL_VALIDATE_CONDITION_WITH_ERROR((shared_event_queue == NULL),NSAPI_ERROR_UNSUPPORTED);
00239 
00240             Callback<void()> mycall(this, &PALSocketWrapper::attachCallback);
00241             attachCallbackObject = mycall;
00242             activeSocket = socket;
00243             socketTypeVal = socketType;
00244             isNonBlockingOnCreation = isNonBlocking;
00245             activeSocket->set_blocking(!isNonBlocking);
00246             if (NULL != callback)
00247             {
00248                 callbackFunction = callback;
00249                 callbackArgument = argument;
00250                 activeSocket->sigio(attachCallbackObject);
00251             }
00252 
00253             initialized = true;
00254             return NSAPI_ERROR_OK;
00255         }
00256 
00257         nsapi_error_t PALSocketWrapper::close()
00258         {
00259             nsapi_error_t status= NSAPI_ERROR_OK;
00260             if (NULL != activeSocket)
00261             {
00262                 status = activeSocket->close();
00263                 delete activeSocket;
00264                 activeSocket = NULL;
00265             }
00266             return  status;
00267         }
00268 
00269         nsapi_error_t PALSocketWrapper::bind(const SocketAddress &address)
00270         {
00271             nsapi_error_t status = NSAPI_ERROR_OK;
00272             PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized), NSAPI_ERROR_PARAMETER);
00273             status= activeSocket->bind(address);
00274             return  status;
00275         }
00276 
00277         void PALSocketWrapper::set_blocking(bool blocking)
00278         {
00279             activeSocket->set_blocking(blocking);
00280         }
00281 
00282         void PALSocketWrapper::set_timeout(int timeout)
00283         {
00284             activeSocket->set_timeout(timeout);
00285         }
00286 
00287         nsapi_error_t PALSocketWrapper::setsockopt(int level, int optname, const void *optval, unsigned optlen)
00288         {
00289             nsapi_error_t status = NSAPI_ERROR_OK;
00290             PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized),NSAPI_ERROR_PARAMETER);
00291             status = activeSocket->setsockopt(level,  optname, optval,  optlen);
00292             return  status;
00293         }
00294 
00295         nsapi_error_t PALSocketWrapper::getsockopt(int level, int optname, void *optval, unsigned *optlen)
00296         {
00297             nsapi_error_t status = NSAPI_ERROR_OK;
00298             PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized),NSAPI_ERROR_PARAMETER);          
00299             status = activeSocket->getsockopt( level,  optname,  optval,  optlen);
00300             return  status;
00301         }
00302 
00303         void PALSocketWrapper::attach(mbed::Callback<void()> func)
00304         {
00305             activeSocket->sigio(func);
00306         }
00307         //void sigio(mbed::Callback<void()> func); // switch attach to sigio for verison 5.4
00308         // nsapi UDP socket funcitons exposed:
00309         nsapi_size_or_error_t PALSocketWrapper::recvfrom(SocketAddress *address, void *data, nsapi_size_t size)
00310         {
00311             nsapi_size_or_error_t status = NSAPI_ERROR_OK;
00312             PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM  != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only
00313 
00314             status = ((UDPSocket*)activeSocket)->recvfrom(address, data,  size);
00315             return  status;
00316         }
00317 
00318         nsapi_size_or_error_t PALSocketWrapper::sendto(const SocketAddress &address, const void *data, nsapi_size_t size)
00319         {
00320             nsapi_size_or_error_t status = NSAPI_ERROR_OK;
00321             PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM  != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only
00322             status = ((UDPSocket*)activeSocket)->sendto(address, data, size);
00323             return  status;
00324         }
00325 
00326         //nsapi TCP socket funcitons exposed:
00327         nsapi_error_t PALSocketWrapper::connect(const SocketAddress &address)
00328         {
00329             nsapi_error_t status = NSAPI_ERROR_OK;
00330             PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER);  // tcp sockets only
00331 
00332             connectState = PAL_PLAT_SOCKET_CONNECTING;
00333             updateCallback(palConnectCallBack); // make sure callback is enabled to see if we get callback to signal connections end
00334             status = ((TCPSocket*)activeSocket)->connect(address);
00335             if (status >= 0 || status == NSAPI_ERROR_IS_CONNECTED)
00336             {
00337                 connectState = PAL_PLAT_SOCKET_CONNECTED;
00338                 updateCallback(NULL); // make sure callback is enabled to see if we get callback to signal connections end
00339             }
00340             else if ((NSAPI_ERROR_WOULD_BLOCK != status) && (NSAPI_ERROR_IN_PROGRESS != status) && (NSAPI_ERROR_ALREADY != status))
00341             {
00342                 connectState = PAL_PLAT_SOCKET_NOT_CONNECTED;
00343             }
00344             return  status;
00345         }
00346 
00347         nsapi_size_or_error_t PALSocketWrapper::send(const void *data, nsapi_size_t size)
00348         {
00349             nsapi_size_or_error_t status = NSAPI_ERROR_OK;
00350             PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // tcp sockets only
00351 
00352             status = ((TCPSocket*)activeSocket)->send( data, size);
00353             return  status;
00354         }
00355 
00356         nsapi_size_or_error_t PALSocketWrapper::recv(void *data, nsapi_size_t size)
00357         {
00358             nsapi_size_or_error_t status = NSAPI_ERROR_OK;
00359             PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)),NSAPI_ERROR_PARAMETER); // tcp sockets only
00360             status = ((TCPSocket*)activeSocket)->recv(data, size);
00361             return  status;
00362         }
00363         //nsapi TCP server socket funcitons exposed:
00364         nsapi_error_t PALSocketWrapper::listen(int backlog )
00365         {
00366             nsapi_error_t status = NSAPI_ERROR_OK;
00367             PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM_SERVER  != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only
00368             status = ((TCPServer*)activeSocket)->listen(backlog);
00369             return  status;
00370         }
00371 
00372         nsapi_error_t PALSocketWrapper::accept(TCPSocket *connection, SocketAddress *address)
00373         {
00374             nsapi_error_t status = NSAPI_ERROR_OK;
00375             PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM_SERVER  != socketTypeVal)),NSAPI_ERROR_PARAMETER); // udp sockets only
00376 
00377             status = ((TCPServer*)activeSocket)->accept(connection, address);
00378             return  status;
00379         }
00380 
00381 
00382 
00383 
00384 PAL_PRIVATE NetworkInterface* s_pal_networkInterfacesSupported[PAL_MAX_SUPORTED_NET_INTERFACES] = { 0 };
00385 
00386 PAL_PRIVATE  uint32_t s_pal_numberOFInterfaces = 0;
00387 
00388 PAL_PRIVATE  uint32_t s_pal_network_initialized = 0;
00389 
00390 PAL_PRIVATE palStatus_t translateErrorToPALError(int errnoValue)
00391 {
00392     palStatus_t status;
00393     switch (errnoValue)
00394     {
00395     case NSAPI_ERROR_NO_MEMORY:
00396         status = PAL_ERR_NO_MEMORY ;
00397         break;
00398     case NSAPI_ERROR_PARAMETER:
00399         status = PAL_ERR_SOCKET_INVALID_VALUE ;
00400         break;
00401     case NSAPI_ERROR_WOULD_BLOCK:
00402         status = PAL_ERR_SOCKET_WOULD_BLOCK ;
00403         break;
00404     case NSAPI_ERROR_DNS_FAILURE:
00405         status = PAL_ERR_SOCKET_DNS_ERROR ;
00406         break;
00407     case NSAPI_ERROR_DHCP_FAILURE:
00408         status = PAL_ERR_SOCKET_HDCP_ERROR ;
00409         break;
00410     case NSAPI_ERROR_AUTH_FAILURE:
00411         status = PAL_ERR_SOCKET_AUTH_ERROR ;
00412         break;
00413     case NSAPI_ERROR_NO_ADDRESS:
00414         status = PAL_ERR_SOCKET_INVALID_ADDRESS ;
00415         break;
00416     case NSAPI_ERROR_NO_CONNECTION:
00417         status = PAL_ERR_SOCKET_NOT_CONNECTED ;
00418         break;
00419     case NSAPI_ERROR_DEVICE_ERROR:
00420         status = PAL_ERR_SOCKET_INPUT_OUTPUT_ERROR ;
00421         break;
00422     case NSAPI_ERROR_UNSUPPORTED:
00423         status = PAL_ERR_NOT_SUPPORTED ;
00424         break;
00425     case NSAPI_ERROR_NO_SOCKET:
00426         status = PAL_ERR_SOCKET_ALLOCATION_FAILED ;
00427         break;
00428     case NSAPI_ERROR_IN_PROGRESS:
00429     case NSAPI_ERROR_ALREADY:
00430         status = PAL_ERR_SOCKET_IN_PROGRES ;
00431         break;
00432     case NSAPI_ERROR_IS_CONNECTED:
00433         status = PAL_SUCCESS;
00434         break;
00435     default:
00436         status = PAL_ERR_SOCKET_GENERIC ;
00437         break;
00438     }
00439     return status;
00440 }
00441 
00442 palStatus_t pal_plat_socketsInit(void* context)
00443 {
00444     (void)context; // replace with macro
00445     int result = PAL_SUCCESS;
00446     if (s_pal_network_initialized == 1)
00447     {
00448         return PAL_SUCCESS; // already initialized.
00449     }
00450 
00451     s_pal_network_initialized = 1;
00452 
00453     return result;
00454 }
00455 
00456 palStatus_t pal_plat_registerNetworkInterface (void* context, uint32_t* interfaceIndex)
00457 {
00458     palStatus_t result = PAL_SUCCESS;
00459     uint32_t index = 0;
00460     bool found = false;
00461 
00462     for (index = 0; index < s_pal_numberOFInterfaces; index++) // if specific context already registered return exisitng index instead of registering again.
00463     {
00464         if (s_pal_networkInterfacesSupported[index] == context)
00465         {
00466             found = true;
00467             *interfaceIndex = index;
00468             break;
00469         }
00470     }
00471 
00472     if (false == found)
00473     {
00474         if (s_pal_numberOFInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES)
00475         {
00476             s_pal_networkInterfacesSupported[s_pal_numberOFInterfaces] = (NetworkInterface*)context;
00477             *interfaceIndex = s_pal_numberOFInterfaces;
00478             ++s_pal_numberOFInterfaces;
00479         }
00480         else
00481         {
00482             result = PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED ;
00483         }
00484     }
00485 
00486     return result;
00487 }
00488 
00489 palStatus_t pal_plat_socketsTerminate (void* context)
00490 {
00491     (void)context; // replace with macro
00492     return PAL_SUCCESS;
00493 }
00494 
00495 PAL_PRIVATE int translateNSAPItoPALSocketOption(int option)
00496 {
00497     int optionVal = PAL_SOCKET_OPTION_ERROR;
00498     switch (option)
00499     {
00500     case PAL_SO_REUSEADDR:
00501         optionVal = NSAPI_REUSEADDR;
00502         break;
00503 #if PAL_NET_TCP_AND_TLS_SUPPORT // socket options below supported only if TCP is supported.
00504     case PAL_SO_KEEPALIVE :
00505         optionVal = NSAPI_KEEPALIVE;
00506         break;
00507     case PAL_SO_KEEPIDLE :
00508         optionVal = NSAPI_KEEPIDLE;
00509         break;
00510     case PAL_SO_KEEPINTVL :
00511         optionVal = NSAPI_KEEPINTVL;
00512         break;
00513 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
00514     case PAL_SO_SNDTIMEO :
00515     case PAL_SO_RCVTIMEO :
00516     default:
00517         optionVal = PAL_SOCKET_OPTION_ERROR;
00518     }
00519     return optionVal;
00520 }
00521 
00522 
00523 PAL_PRIVATE palStatus_t palSockAddrToSocketAddress(const palSocketAddress_t* palAddr, int length, SocketAddress& output)
00524 {
00525     palStatus_t result = PAL_SUCCESS;
00526     uint16_t port = 0;
00527     nsapi_version_t version = NSAPI_IPv4;
00528 
00529     result = pal_getSockAddrPort(palAddr, &port);
00530     if (result != PAL_SUCCESS)
00531     {
00532         return result;
00533     }
00534     output.set_port(port);
00535 
00536     if (PAL_AF_INET == palAddr->addressType)
00537     {
00538         palIpV4Addr_t ipV4Addr;
00539         version = NSAPI_IPv4;
00540         result = pal_getSockAddrIPV4Addr(palAddr, ipV4Addr);
00541         if (result == PAL_SUCCESS)
00542         {
00543             output.set_ip_bytes(&ipV4Addr, version);
00544         }
00545     }
00546     else if (PAL_AF_INET6  == palAddr->addressType)
00547     {
00548         palIpV6Addr_t ipV6Addr;
00549         version = NSAPI_IPv6;
00550         result = pal_getSockAddrIPV6Addr(palAddr, ipV6Addr);
00551         if (result == PAL_SUCCESS)
00552         {
00553             output.set_ip_bytes(&ipV6Addr, version);
00554         }
00555     }
00556 
00557     return result;
00558 }
00559 
00560 PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSocketAddress_t* out, palSocketLength_t* length)
00561 {
00562     palStatus_t result = PAL_SUCCESS;
00563     int index = 0;
00564 
00565     if (input.get_ip_version() == NSAPI_IPv4)
00566     {
00567         palIpV4Addr_t addr;
00568         const void* tmp = input.get_ip_bytes();
00569         for (index = 0; index < PAL_IPV4_ADDRESS_SIZE; index++)
00570         {
00571             addr[index] = ((const uint8_t*)tmp)[index];
00572         }
00573         result = pal_setSockAddrIPV4Addr(out, addr);
00574         *length = PAL_NET_MAX_ADDR_SIZE;  // TODO: check
00575 
00576     }
00577     else if (input.get_ip_version() == NSAPI_IPv6)
00578     {
00579         palIpV6Addr_t addr;
00580         const void* tmp = input.get_ip_bytes();
00581         for (index = 0; index < PAL_IPV6_ADDRESS_SIZE; index++)
00582         {
00583             addr[index] = ((const uint8_t*)tmp)[index];
00584         }
00585         result = pal_setSockAddrIPV6Addr(out, addr);
00586         *length = PAL_NET_MAX_ADDR_SIZE;  // TODO: check
00587     }
00588     else
00589     {
00590         result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY ;
00591     }
00592 
00593     if (result == PAL_SUCCESS)
00594     {
00595         result = pal_setSockAddrPort(out, input.get_port());
00596     }
00597     return result;
00598 }
00599 
00600 
00601 
00602 
00603 palStatus_t pal_plat_socket (palSocketDomain_t  domain, palSocketType_t  type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* socket)
00604 {
00605     int result = PAL_SUCCESS;
00606     PALSocketWrapper* socketObj = NULL;
00607     Socket* internalSocket = NULL;
00608 
00609     PAL_VALIDATE_ARGUMENTS((NULL == socket))
00610 
00611     if (PAL_NET_DEFAULT_INTERFACE == interfaceNum)
00612     {
00613         interfaceNum = 0;
00614     }
00615 
00616     if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_DGRAM  == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6  == domain) || (PAL_AF_UNSPEC == domain))) // check correct parameters for UDP socket
00617     {
00618         internalSocket = new UDPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
00619     }
00620 #if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
00621     else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6  == domain) || (PAL_AF_UNSPEC == domain))) // check correct parameters for TCP socket
00622     {
00623         internalSocket = new TCPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
00624     }
00625     else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM_SERVER  == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6  == domain) || (PAL_AF_UNSPEC == domain))) // check correct parameters for TCP Server socket
00626     {
00627         internalSocket = new TCPServer(s_pal_networkInterfacesSupported[interfaceNum]);
00628     }
00629 #endif
00630     else
00631     {
00632         result =  PAL_ERR_INVALID_ARGUMENT ;
00633     }
00634 
00635     if ((PAL_SUCCESS == result ) && (NULL == internalSocket))
00636     {
00637         result = PAL_ERR_NO_MEMORY ;
00638     }
00639 
00640     if (PAL_SUCCESS == result)
00641     {
00642 
00643         socketObj = new PALSocketWrapper();
00644         if (NULL != socketObj)
00645         {
00646             if (0 == socketObj->initialize(internalSocket, type, nonBlockingSocket, NULL, NULL))
00647             {
00648                 *socket = (palSocket_t )socketObj;
00649             }
00650             else
00651             {
00652                 result = PAL_ERR_INVALID_ARGUMENT ;
00653             }
00654 
00655         }
00656         else
00657         {
00658             delete internalSocket;
00659             result = PAL_ERR_NO_MEMORY ;
00660         }
00661 
00662     }
00663 
00664     if (PAL_SUCCESS != result) //cleanup
00665     {
00666         if (NULL != internalSocket)
00667         {
00668             delete internalSocket;
00669         }
00670         if (NULL != socketObj)
00671         {
00672             delete socketObj;
00673         }
00674     }
00675     return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
00676 }
00677 
00678 
00679 palStatus_t pal_plat_setSocketOptions (palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength)
00680 {
00681     int result = PAL_SUCCESS;
00682     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
00683     int socketOption = PAL_SOCKET_OPTION_ERROR;
00684 
00685     PAL_VALIDATE_ARGUMENTS(NULL == socket);
00686 
00687     socketOption = translateNSAPItoPALSocketOption(optionName);
00688     if (PAL_SOCKET_OPTION_ERROR != socketOption)
00689     {
00690         if (PAL_SO_REUSEADDR == optionName)
00691         {
00692             result = socketObj->setsockopt(NSAPI_SOCKET, socketOption, optionValue, optionLength);
00693         }
00694 #if PAL_NET_TCP_AND_TLS_SUPPORT
00695         else if (PAL_SO_KEEPIDLE  == optionName ||
00696                  PAL_SO_KEEPINTVL  == optionName )
00697         {
00698                 // Timeouts are in milliseconds
00699                 uint32_t timeout = (*(int *)optionValue) * 1000;
00700                 result = socketObj->setsockopt(NSAPI_SOCKET, socketOption, (void*)&timeout, sizeof(timeout));
00701         }
00702 #endif
00703         else
00704         {
00705             result = socketObj->setsockopt(NSAPI_SOCKET, socketOption, optionValue, optionLength);
00706         }
00707 
00708         if (result < 0)
00709         {
00710             result = translateErrorToPALError(result);
00711         }
00712     }
00713     else
00714     {
00715         if ((PAL_SO_SNDTIMEO  == optionName) || (PAL_SO_RCVTIMEO  == optionName)) // timeouts in MBED API are not managed though socket options, bun instead via a different funciton call
00716         {
00717             int timeout = *((int*)optionValue);
00718             // SO_xxxTIMEO should only affect blocking sockets - it only limits the block,
00719             // whereas NSAPI's set_timeout is coupled with the blocking setting
00720             if (!socketObj->isNonBlocking()) {
00721                 socketObj->set_timeout(timeout);
00722             }
00723         }
00724         else
00725         {
00726             result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED ;
00727         }
00728     }
00729 
00730 
00731     return result;
00732 }
00733 
00734 palStatus_t pal_plat_isNonBlocking (palSocket_t socket, bool* isNonBlocking)
00735 {
00736     PALSocketWrapper* socketObj =  NULL;
00737     PAL_VALIDATE_ARGUMENTS(NULL == socket);
00738     
00739     socketObj =  (PALSocketWrapper*)socket;
00740 
00741     *isNonBlocking = socketObj->isNonBlocking();
00742 
00743     return PAL_SUCCESS;
00744 
00745 }
00746 
00747 palStatus_t pal_plat_bind (palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength)
00748 {
00749     int result = PAL_SUCCESS;
00750     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
00751     SocketAddress internalAddr;
00752 
00753     PAL_VALIDATE_ARGUMENTS ((NULL == socket));
00754 
00755     result = palSockAddrToSocketAddress(myAddress, addressLength, internalAddr);
00756     if (result == 0)
00757     {
00758         result = socketObj->bind(internalAddr);
00759         if (result < 0)
00760         {
00761             result =  translateErrorToPALError(result);
00762         }
00763     }
00764 
00765     return result;
00766 }
00767 
00768 
00769 palStatus_t pal_plat_receiveFrom (palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived)
00770 {
00771     int result = PAL_SUCCESS;
00772     int status = 0;
00773     *bytesReceived = 0;
00774     SocketAddress sockAddr;
00775     PALSocketWrapper* socketObj;
00776     uint8_t* internalBufferPtr = (uint8_t*)buffer;
00777     uint32_t bufferUsed = 0;
00778 
00779     PAL_VALIDATE_ARGUMENTS((NULL == socket));
00780 
00781     socketObj = (PALSocketWrapper*)socket;
00782 
00783     if (true == socketObj->isRxBufferSet())
00784     {
00785         internalBufferPtr[0] = socketObj->getAndResetRxBuffer();
00786         internalBufferPtr++;
00787         length--;
00788         bufferUsed += 1;
00789     }
00790 
00791     if (length > 0)
00792     {
00793         status = socketObj->recvfrom(&sockAddr, internalBufferPtr, length);
00794         if (status < 0)
00795         {
00796             result = translateErrorToPALError(status);
00797         }
00798         else if (status == 0)
00799         {
00800             result = PAL_ERR_SOCKET_CONNECTION_CLOSED ;
00801         }
00802         else // only return address / bytesReceived in case of success
00803         {
00804             if ((NULL != from) && (NULL != fromLength))
00805             {
00806                 result = socketAddressToPalSockAddr(sockAddr, from, fromLength);
00807             }
00808             *bytesReceived = status + bufferUsed;
00809         }
00810     }
00811     else
00812     {
00813         *bytesReceived = bufferUsed;
00814     }
00815 
00816     return result;
00817 
00818 }
00819 
00820 palStatus_t pal_plat_sendTo (palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent)
00821 {
00822     int result = PAL_SUCCESS;
00823     int status = 0;
00824     SocketAddress sockAddr;
00825 
00826     PAL_VALIDATE_ARGUMENTS((NULL == socket));
00827 
00828     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
00829 
00830     *bytesSent = 0;
00831     result = palSockAddrToSocketAddress(to, toLength, sockAddr);
00832     if (result == 0)
00833     {
00834         status = socketObj->sendto(sockAddr, buffer, length);
00835         if (status < 0)
00836         {
00837             result = translateErrorToPALError(status);
00838         }
00839         else
00840         {
00841             *bytesSent = status;
00842         }
00843     }
00844 
00845     return result;
00846 }
00847 
00848 palStatus_t pal_plat_close (palSocket_t* socket)
00849 {
00850     int result = PAL_SUCCESS;
00851     if (NULL == *socket)
00852     {
00853         PAL_LOG(DBG, "socket close called on socket which was already closed");
00854         return result; // socket already closed (or not opened) - no need to close.
00855     }
00856     PALSocketWrapper* socketObj = (PALSocketWrapper*)*socket;
00857     result = socketObj->close();
00858     if (result < 0)
00859     {
00860         result =  translateErrorToPALError(result);
00861     }
00862     delete socketObj;
00863     *socket = NULL;
00864     return result;
00865 }
00866 
00867 palStatus_t pal_plat_getNumberOfNetInterfaces ( uint32_t* numInterfaces)
00868 {
00869     *numInterfaces =  s_pal_numberOFInterfaces;
00870     return PAL_SUCCESS;
00871 }
00872 
00873 palStatus_t pal_plat_getNetInterfaceInfo (uint32_t interfaceNum, palNetInterfaceInfo_t  * interfaceInfo)
00874 {
00875     palStatus_t result = PAL_SUCCESS;
00876     const char* address = NULL;
00877     SocketAddress addr;
00878     PAL_VALIDATE_ARGUMENTS((interfaceNum >= s_pal_numberOFInterfaces));
00879 
00880     address = s_pal_networkInterfacesSupported[interfaceNum]->get_ip_address(); // ip address returned is a null terminated string
00881     if (NULL != address)
00882     {
00883         addr.set_ip_address(address);
00884         result = socketAddressToPalSockAddr(addr, &interfaceInfo->address, &interfaceInfo->addressSize);
00885     }
00886 
00887 
00888     return result;
00889 }
00890 
00891 typedef void(*palSelectCallbackFunction_t)();
00892 
00893 PAL_PRIVATE palSemaphoreID_t s_palSelectSemaphore = 0;
00894 PAL_PRIVATE bool s_palSelectSemaphoreInited = false;
00895 uint32_t s_select_event_happened[PAL_NET_SOCKET_SELECT_MAX_SOCKETS];
00896 
00897 // select callbacks definition
00898 // TODO: nirson01 change to define these using a macro.
00899 void palSelectCallback0()
00900 {
00901     s_select_event_happened[0]++;
00902     pal_osSemaphoreRelease(s_palSelectSemaphore);
00903 }
00904 void palSelectCallback1()
00905 {
00906     s_select_event_happened[1]++;
00907     pal_osSemaphoreRelease(s_palSelectSemaphore);
00908 }
00909 void palSelectCallback2()
00910 {
00911     s_select_event_happened[2]++;
00912     pal_osSemaphoreRelease(s_palSelectSemaphore);
00913 }
00914 void palSelectCallback3()
00915 {
00916     s_select_event_happened[3]++;
00917     pal_osSemaphoreRelease(s_palSelectSemaphore);
00918 }
00919 void palSelectCallback4()
00920 {
00921     s_select_event_happened[4]++;
00922     pal_osSemaphoreRelease(s_palSelectSemaphore);
00923 }
00924 void palSelectCallback5()
00925 {
00926     s_select_event_happened[5]++;
00927     pal_osSemaphoreRelease(s_palSelectSemaphore);
00928 }
00929 void palSelectCallback6()
00930 {
00931     s_select_event_happened[6]++;
00932     pal_osSemaphoreRelease(s_palSelectSemaphore);
00933 }
00934 void palSelectCallback7()
00935 {
00936     s_select_event_happened[7]++;
00937     pal_osSemaphoreRelease(s_palSelectSemaphore);
00938 }
00939 
00940 palSelectCallbackFunction_t s_palSelectPalCallbackFunctions[PAL_NET_SOCKET_SELECT_MAX_SOCKETS] = { palSelectCallback0, palSelectCallback1, palSelectCallback2, palSelectCallback3, palSelectCallback4, palSelectCallback5, palSelectCallback6, palSelectCallback7 };
00941 
00942 
00943 #if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
00944 
00945 
00946 palStatus_t pal_plat_listen (palSocket_t socket, int backlog)
00947 {
00948     int result = PAL_SUCCESS;
00949     PAL_VALIDATE_ARGUMENTS(NULL == socket);
00950 
00951     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;    
00952     result = socketObj->listen(backlog);
00953     if (result < 0)
00954     {
00955         return translateErrorToPALError(result);
00956     }
00957     return PAL_SUCCESS;
00958 }
00959 
00960 
00961 palStatus_t pal_plat_accept (palSocket_t socket, palSocketAddress_t * address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket)
00962 {
00963     int result = PAL_SUCCESS;
00964 
00965     SocketAddress incomingAddr;
00966 
00967     PAL_VALIDATE_ARGUMENTS ((NULL == socket));
00968 
00969     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
00970     result = socketObj->accept( (TCPSocket*)(*(PALSocketWrapper**)acceptedSocket)->getActiveSocket(), &incomingAddr);
00971     if (result < 0)
00972     {
00973         result = translateErrorToPALError(result);
00974     }
00975     else
00976     {
00977         result = socketAddressToPalSockAddr(incomingAddr, address, addressLen);
00978     }
00979     return result;
00980 }
00981 
00982 
00983 palStatus_t pal_plat_connect (palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen)
00984 {
00985     int result = PAL_SUCCESS;
00986     SocketAddress internalAddr;
00987     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
00988     PAL_VALIDATE_ARGUMENTS ((NULL == socket));
00989 
00990     result = palSockAddrToSocketAddress(address, addressLen,  internalAddr);
00991     if (result == PAL_SUCCESS)
00992     {
00993         result = socketObj->connect(internalAddr);
00994         if (result < 0)
00995         {
00996             result =  translateErrorToPALError(result);
00997         }
00998     }
00999 
01000     return result;
01001 }
01002 
01003 palStatus_t pal_plat_recv (palSocket_t socket, void *buf, size_t len, size_t* recievedDataSize)
01004 {
01005     int result = PAL_SUCCESS;
01006     int status = 0;
01007     uint8_t* internalBufferPtr = (uint8_t*)buf;
01008     uint32_t bufferUsed = 0;
01009 
01010     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
01011     PAL_VALIDATE_ARGUMENTS ((NULL == socket));
01012 
01013     if (true == socketObj->isRxBufferSet())
01014     {
01015         internalBufferPtr[0] = socketObj->getAndResetRxBuffer();
01016         internalBufferPtr++;
01017         len--;
01018         bufferUsed += 1;
01019     }
01020 
01021     if (len > 0)
01022     {
01023         status = socketObj->recv(internalBufferPtr, len);
01024         if (status < 0)
01025         {
01026             result = translateErrorToPALError(status);
01027         }
01028         else if (status == 0) {
01029             return PAL_ERR_SOCKET_CONNECTION_CLOSED ;
01030         }
01031     }
01032     *recievedDataSize = status + bufferUsed;
01033     return result;
01034 }
01035 
01036 palStatus_t pal_plat_send (palSocket_t socket, const void *buf, size_t len, size_t* sentDataSize)
01037 {
01038     palStatus_t result = PAL_SUCCESS;
01039     int status = 0;
01040 
01041     PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
01042     PAL_VALIDATE_ARGUMENTS ((NULL == socket));
01043 
01044     status = socketObj->send(buf, len);
01045     if (status < 0)
01046     {
01047         result = translateErrorToPALError(status);
01048     }
01049     else
01050     {
01051         *sentDataSize = status;
01052     }
01053     return result;
01054 }
01055 
01056 #endif //PAL_NET_TCP_AND_TLS_SUPPORT
01057 
01058 
01059 #if PAL_NET_ASYNCHRONOUS_SOCKET_API
01060 
01061 
01062 palStatus_t pal_plat_asynchronousSocket (palSocketDomain_t  domain, palSocketType_t  type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t  callback, void* arg,  palSocket_t* socket)
01063 {
01064     int result = PAL_SUCCESS;
01065     PALSocketWrapper * socketObj = NULL;
01066     Socket* internalSocket = NULL;
01067 
01068     PAL_VALIDATE_ARGUMENTS((NULL == socket));
01069 
01070     if (PAL_NET_DEFAULT_INTERFACE == interfaceNum)
01071     {
01072         interfaceNum = 0;
01073     }
01074 
01075     if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_DGRAM  == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6  == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for UDP socket
01076     {
01077         internalSocket = new UDPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
01078     }
01079 #if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
01080     else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6  == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for TCP socket
01081     {
01082         internalSocket = new TCPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
01083     }
01084     else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM_SERVER  == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6  == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for TCP Server socket
01085     {
01086         internalSocket = new TCPServer(s_pal_networkInterfacesSupported[interfaceNum]);
01087     }
01088 #endif
01089     else
01090     {
01091         result = PAL_ERR_INVALID_ARGUMENT ;
01092     }
01093 
01094     if ((PAL_SUCCESS == result) && (NULL == internalSocket))
01095     {
01096         result = PAL_ERR_NO_MEMORY ;
01097     }
01098 
01099     if (PAL_SUCCESS == result)
01100     {
01101         socketObj = new PALSocketWrapper();
01102         if (NULL != socketObj)
01103         {
01104             if (0 == socketObj->initialize(internalSocket, type, nonBlockingSocket, callback, arg))
01105             {
01106                 *socket = (palSocket_t )socketObj;
01107             }
01108             else
01109             {
01110                 result = PAL_ERR_INVALID_ARGUMENT ;
01111             }
01112         }
01113         else
01114         {
01115             delete internalSocket;
01116             result = PAL_ERR_NO_MEMORY ;
01117         }
01118     }
01119 
01120     if (PAL_SUCCESS != result) //cleanup
01121     {
01122         if (NULL != internalSocket)
01123         {
01124             delete internalSocket;
01125         }
01126         if (NULL != socketObj)
01127         {
01128             delete socketObj;
01129         }
01130     }
01131     return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
01132 }
01133 
01134 #endif
01135 
01136 #if PAL_NET_DNS_SUPPORT
01137 
01138 palStatus_t pal_plat_getAddressInfo (const char *url, palSocketAddress_t *address, palSocketLength_t* length)
01139 {
01140     palStatus_t result = PAL_SUCCESS;
01141     SocketAddress zeroAddress("0.0.0.0"); // zero address for check
01142     SocketAddress translatedAddress; // by default use the fist supported net interface - TODO: do we need to select a different interface?
01143 
01144 
01145 #if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY
01146     result = s_pal_networkInterfacesSupported[0]->gethostbyname(url, &translatedAddress);
01147 #elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY
01148     result = s_pal_networkInterfacesSupported[0]->gethostbyname(url, &translatedAddress, NSAPI_IPv4);
01149 #elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY
01150     result = s_pal_networkInterfacesSupported[0]->gethostbyname(url, &translatedAddress, NSAPI_IPv6);
01151 #else
01152 #error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value.
01153 #endif
01154 
01155     if (result == 0)
01156     {
01157         if (zeroAddress == translatedAddress) // got zero address - return error
01158         {
01159             result = PAL_ERR_SOCKET_DNS_ERROR ;
01160         }
01161         else // address ok
01162         {
01163             result = socketAddressToPalSockAddr(translatedAddress, address, length);
01164         }
01165 
01166     }
01167     else // error happened
01168     {
01169         result = translateErrorToPALError(result);
01170     }
01171     return result;
01172 }
01173 
01174 #endif
01175 
01176