PageRenderTime 136ms CodeModel.GetById 21ms app.highlight 104ms RepoModel.GetById 1ms app.codeStats 1ms

/DeviceCode/pal/COM/sockets/sockets.cpp

https://bitbucket.org/CW2/netduinofirmware
C++ | 1485 lines | 1022 code | 295 blank | 168 comment | 177 complexity | 2b98d70dc4199a57c38dbad01030b274 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   2// Copyright (c) Microsoft Corporation.  All rights reserved.
   3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   4
   5#include "sockets.h"
   6
   7//--//
   8
   9#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
  10#pragma arm section zidata = "g_PAL_Sockets_Driver"
  11#endif
  12
  13Sockets_Driver g_Sockets_Driver;
  14
  15#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
  16#pragma arm section zidata
  17#endif
  18
  19HAL_COMPLETION Sockets_Driver::s_DebuggerTimeoutCompletion;
  20
  21//--//
  22
  23SOCK_SOCKET SOCK_socket( INT32 family, INT32 type, INT32 protocol ) 
  24{ 
  25    NATIVE_PROFILE_PAL_COM();
  26    return Sockets_Driver::Socket( family, type, protocol, FALSE );
  27}
  28INT32 SOCK_bind( SOCK_SOCKET socket, const struct SOCK_sockaddr* address, INT32 addressLen  ) 
  29{ 
  30    NATIVE_PROFILE_PAL_COM();
  31    return HAL_SOCK_bind( socket, address, addressLen  );
  32}
  33INT32 SOCK_connect(SOCK_SOCKET socket, const struct SOCK_sockaddr* address, INT32 addressLen) 
  34{ 
  35    NATIVE_PROFILE_PAL_COM();
  36    return Sockets_Driver::Connect(socket, address, addressLen);
  37}
  38INT32 SOCK_send(SOCK_SOCKET socket, const char* buf, INT32 len, INT32 flags) 
  39{ 
  40    NATIVE_PROFILE_PAL_COM();
  41    return Sockets_Driver::Send(socket, buf, len, flags);
  42}
  43INT32 SOCK_recv(SOCK_SOCKET socket, char* buf, INT32 len, INT32 flags)
  44{ 
  45    NATIVE_PROFILE_PAL_COM();
  46    return Sockets_Driver::Recv(socket, buf, len, flags);
  47}
  48INT32 SOCK_close(SOCK_SOCKET socket)
  49{ 
  50    NATIVE_PROFILE_PAL_COM();
  51    return Sockets_Driver::Close(socket);
  52}
  53INT32 SOCK_listen( SOCK_SOCKET socket, INT32 backlog )
  54{ 
  55    NATIVE_PROFILE_PAL_COM();
  56    return Sockets_Driver::Listen( socket, backlog );
  57}
  58SOCK_SOCKET SOCK_accept( SOCK_SOCKET socket, struct SOCK_sockaddr* address, INT32* addressLen )
  59{ 
  60    NATIVE_PROFILE_PAL_COM();
  61    return Sockets_Driver::Accept( socket, address, addressLen, FALSE );
  62}
  63INT32 SOCK_shutdown( SOCK_SOCKET socket, INT32 how )
  64{ 
  65    NATIVE_PROFILE_PAL_COM();
  66    return HAL_SOCK_shutdown( socket, how );
  67}
  68INT32 SOCK_getaddrinfo( const char* nodename, char* servname, const struct SOCK_addrinfo* hints, struct SOCK_addrinfo** res )
  69{ 
  70    NATIVE_PROFILE_PAL_COM();
  71    return HAL_SOCK_getaddrinfo( nodename, servname, hints, res );
  72}
  73void SOCK_freeaddrinfo( struct SOCK_addrinfo* ai )
  74{ 
  75    NATIVE_PROFILE_PAL_COM();
  76    HAL_SOCK_freeaddrinfo( ai );
  77}
  78INT32 SOCK_ioctl( SOCK_SOCKET socket, INT32 cmd, INT32* data )
  79{ 
  80    NATIVE_PROFILE_PAL_COM();
  81    return HAL_SOCK_ioctl( socket, cmd, data );
  82}
  83INT32 SOCK_getlasterror()
  84{ 
  85    NATIVE_PROFILE_PAL_COM();
  86    return HAL_SOCK_getlasterror();
  87}
  88INT32 SOCK_select( INT32 nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* except, const struct SOCK_timeval* timeout )
  89{ 
  90    NATIVE_PROFILE_PAL_COM();
  91    return Sockets_Driver::Select( nfds, readfds, writefds, except, timeout );
  92}
  93INT32 SOCK_setsockopt( SOCK_SOCKET socket, INT32 level, INT32 optname, const char* optval, INT32  optlen )
  94{ 
  95    NATIVE_PROFILE_PAL_COM();
  96    return HAL_SOCK_setsockopt( socket, level, optname, optval, optlen );
  97}
  98INT32 SOCK_getsockopt( SOCK_SOCKET socket, INT32 level, INT32 optname,       char* optval, INT32* optlen )
  99{ 
 100    NATIVE_PROFILE_PAL_COM();
 101    return HAL_SOCK_getsockopt( socket, level, optname, optval, optlen );
 102}
 103INT32 SOCK_getpeername( SOCK_SOCKET socket, struct SOCK_sockaddr* name, INT32* namelen )
 104{ 
 105    NATIVE_PROFILE_PAL_COM();
 106    return HAL_SOCK_getpeername( socket, name, namelen );
 107}
 108INT32 SOCK_getsockname( SOCK_SOCKET socket, struct SOCK_sockaddr* name, INT32* namelen )
 109{ 
 110    NATIVE_PROFILE_PAL_COM();
 111    return HAL_SOCK_getsockname( socket, name, namelen );
 112}
 113INT32 SOCK_recvfrom( SOCK_SOCKET s, char* buf, INT32 len, INT32 flags, struct SOCK_sockaddr* from, INT32* fromlen )
 114{ 
 115    NATIVE_PROFILE_PAL_COM();
 116    return Sockets_Driver::RecvFrom( s, buf, len, flags, from, fromlen );
 117}
 118INT32 SOCK_sendto( SOCK_SOCKET s, const char* buf, INT32 len, INT32 flags, const struct SOCK_sockaddr* to, INT32 tolen )
 119{ 
 120    NATIVE_PROFILE_PAL_COM();
 121    return Sockets_Driver::SendTo( s, buf, len, flags, to, tolen );
 122}
 123
 124BOOL Network_Initialize()
 125{
 126    NATIVE_PROFILE_PAL_COM();
 127    return Sockets_Driver::Initialize( );
 128}
 129
 130BOOL Network_Uninitialize()
 131{
 132    NATIVE_PROFILE_PAL_COM();
 133    return Sockets_Driver::Uninitialize( );
 134}
 135
 136void Sockets_Driver::CloseDebuggerSocket()
 137{
 138    GLOBAL_LOCK_SOCKETS(lock);
 139
 140    if(g_Sockets_Driver.m_SocketDebugStream != SOCK_SOCKET_ERROR)
 141    {
 142        SOCK_close( g_Sockets_Driver.m_SocketDebugStream );
 143        
 144        g_Sockets_Driver.m_SocketDebugStream = SOCK_SOCKET_ERROR;
 145
 146        g_Sockets_Driver.m_stateDebugSocket = DbgSock_Listening;
 147
 148        if(s_DebuggerTimeoutCompletion.IsLinked())
 149        {
 150            s_DebuggerTimeoutCompletion.Abort();
 151        }
 152    }
 153}
 154
 155void Sockets_Driver::OnDebuggerTimeout(void* arg)
 156{
 157    CloseDebuggerSocket();
 158}
 159
 160BOOL  SOCKETS_Initialize( int ComPortNum )
 161{
 162    NATIVE_PROFILE_PAL_COM();
 163
 164    return Sockets_Driver::InitializeDbgListener( ComPortNum );
 165}
 166BOOL  SOCKETS_Uninitialize( int ComPortNum )
 167{
 168    NATIVE_PROFILE_PAL_COM();
 169    return Sockets_Driver::UninitializeDbgListener( ComPortNum );
 170}
 171
 172INT32 SOCKETS_Write( INT32 ComPortNum, const char* Data, size_t size )
 173{
 174    NATIVE_PROFILE_PAL_COM();
 175    return Sockets_Driver::Write( ComPortNum, Data, size );
 176}
 177
 178INT32 SOCKETS_Read( INT32 ComPortNum, char* Data, size_t size )
 179{
 180    NATIVE_PROFILE_PAL_COM();
 181    return Sockets_Driver::Read( ComPortNum, Data, size );
 182}
 183
 184BOOL SOCKETS_Flush( INT32 ComPortNum )
 185{
 186    NATIVE_PROFILE_PAL_COM();
 187    return TRUE;
 188}
 189
 190BOOL SOCKETS_UpgradeToSsl( INT32 ComPortNum, const UINT8* pCACert, UINT32 caCertLen, const UINT8* pDeviceCert, UINT32 deviceCertLen, LPCSTR szTargetHost )
 191{
 192    NATIVE_PROFILE_PAL_COM();
 193    return FALSE;
 194}
 195
 196BOOL SOCKETS_IsUsingSsl( INT32 ComPortNum )
 197{
 198    NATIVE_PROFILE_PAL_COM();
 199    return FALSE;
 200}
 201
 202void SOCKETS_CloseConnections()
 203{
 204    NATIVE_PROFILE_PAL_COM();
 205    Sockets_Driver::CloseConnections(FALSE);
 206}
 207
 208BOOL SOCKETS_ProcessSocketActivity(SOCK_SOCKET signalSocket)
 209{
 210    NATIVE_PROFILE_PAL_COM();
 211    return Sockets_Driver::ProcessSocketActivity(signalSocket);
 212}
 213
 214UINT32 SOCK_CONFIGURATION_GetAdapterCount()
 215{
 216    NATIVE_PROFILE_PAL_COM();
 217    return HAL_SOCK_CONFIGURATION_GetAdapterCount();
 218}
 219
 220HRESULT SOCK_CONFIGURATION_LoadAdapterConfiguration( UINT32 interfaceIndex, SOCK_NetworkConfiguration* config )
 221{
 222    NATIVE_PROFILE_PAL_COM();
 223    return HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(interfaceIndex, config);
 224}
 225HRESULT SOCK_CONFIGURATION_UpdateAdapterConfiguration( UINT32 interfaceIndex, UINT32 updateFlags, SOCK_NetworkConfiguration* config )
 226{
 227    NATIVE_PROFILE_PAL_COM();
 228    HRESULT hr = S_OK;
 229    BOOL fDbg = FALSE;
 230
 231    if(interfaceIndex >= NETWORK_INTERFACE_COUNT) 
 232    {
 233        return CLR_E_INVALID_PARAMETER;
 234    }
 235
 236    const UINT32 c_reInitFlag = SOCK_NETWORKCONFIGURATION_UPDATE_DHCP       | 
 237                                SOCK_NETWORKCONFIGURATION_UPDATE_DHCP_RENEW | 
 238                                SOCK_NETWORKCONFIGURATION_UPDATE_MAC;
 239
 240    const UINT32 c_uninitFlag = c_reInitFlag | SOCK_NETWORKCONFIGURATION_UPDATE_DHCP_RELEASE;
 241
 242    if(0 != (updateFlags & c_uninitFlag))
 243    {
 244        fDbg = SOCKETS_Uninitialize(COM_SOCKET_DBG);
 245    }
 246
 247    hr = HAL_SOCK_CONFIGURATION_UpdateAdapterConfiguration(interfaceIndex, updateFlags, config);
 248
 249    if(SUCCEEDED(hr))
 250    {
 251        Sockets_Driver::SaveConfig(interfaceIndex, config);
 252    }
 253    else
 254    {
 255        // restore the network configuration
 256        HAL_SOCK_CONFIGURATION_UpdateAdapterConfiguration(interfaceIndex, updateFlags, &g_NetworkConfig.NetworkInterfaces[interfaceIndex]);
 257    }
 258
 259    if(0 != (updateFlags & c_reInitFlag))
 260    {
 261        if(fDbg) SOCKETS_Initialize(COM_SOCKET_DBG);
 262    }
 263
 264    return hr;
 265}
 266
 267HRESULT SOCK_CONFIGURATION_LoadConfiguration( UINT32 interfaceIndex, SOCK_NetworkConfiguration* config )
 268{
 269    NATIVE_PROFILE_PAL_COM();
 270    HRESULT hr = S_OK;
 271
 272    if(interfaceIndex >= NETWORK_INTERFACE_COUNT || config == NULL) 
 273    {
 274        return CLR_E_INVALID_PARAMETER;
 275    }
 276
 277    // load current DCHP settings
 278    hr = SOCK_CONFIGURATION_LoadAdapterConfiguration(interfaceIndex, config);
 279
 280    return hr;
 281}
 282
 283HRESULT SOCK_CONFIGURATION_LoadWirelessConfiguration( UINT32 interfaceIndex, SOCK_WirelessConfiguration* wirelessConfig )
 284{
 285    NATIVE_PROFILE_PAL_COM();
 286
 287    if (interfaceIndex >= WIRELESS_INTERFACE_COUNT)
 288    {
 289        return CLR_E_INVALID_PARAMETER;
 290    }
 291
 292    Sockets_Driver::ApplyWirelessConfig();
 293
 294    /// Hal version is given a chance if it wants to override stored predifned values.
 295    if (HAL_SOCK_CONFIGURATION_LoadWirelessConfiguration(interfaceIndex, wirelessConfig) != S_OK)
 296    {
 297        memcpy( wirelessConfig, &g_WirelessConfig.WirelessInterfaces[interfaceIndex], sizeof(SOCK_WirelessConfiguration) );
 298    }
 299
 300    return S_OK;
 301}
 302
 303HRESULT SOCK_CONFIGURATION_UpdateWirelessConfiguration( UINT32 interfaceIndex, SOCK_WirelessConfiguration* wirelessConfig )
 304{
 305    NATIVE_PROFILE_PAL_COM();
 306
 307    if (interfaceIndex >= WIRELESS_INTERFACE_COUNT)
 308    {
 309        return CLR_E_INVALID_PARAMETER;
 310    }
 311
 312    memcpy( &g_WirelessConfig.WirelessInterfaces[interfaceIndex], wirelessConfig, sizeof(SOCK_WirelessConfiguration) );
 313
 314    return S_OK;
 315}
 316
 317HRESULT SOCK_CONFIGURATION_SaveAllWirelessConfigurations( )
 318{
 319    HAL_CONFIG_BLOCK::UpdateBlockWithName(g_WirelessConfig.GetDriverName(), &g_WirelessConfig, sizeof(g_WirelessConfig), TRUE);
 320
 321    return S_OK;
 322}
 323
 324
 325#define SOCKET_SHUTDOWN_READ         0
 326#define SOCKET_SHUTDOWN_WRITE        1
 327#define SOCKET_SHUTDOWN_READ_WRITE   2
 328
 329#define ISSET_SOCKET_FLAG(x,y) ((y) == ((y) & (x).m_flags))
 330#define SET_SOCKET_FLAG(x,y)   (x).m_flags |= (y)
 331#define CLEAR_SOCKET_FLAG(x,y) (x).m_flags &= ~(y)
 332
 333//-----------------------------------------------------------------------------
 334//
 335//  CloseConnections - close all connections with the option of leaving the debugger sockets open.
 336//  debugger sockets are left open on CLR reboot so that communication with the debugger is not
 337//  lost.
 338//
 339//-----------------------------------------------------------------------------
 340void Sockets_Driver::CloseConnections(BOOL fCloseDbg)
 341{
 342    NATIVE_PROFILE_PAL_COM();
 343    GLOBAL_LOCK_SOCKETS(lock);
 344
 345    if(fCloseDbg)
 346    {
 347        // this has to be set if we are closing all debugger connections, or the thread will abort
 348        g_Sockets_Driver.m_fShuttingDown = TRUE;
 349    }
 350
 351    // For some platforms (NetOS) we need to close the socket on a separate socket thread,
 352    // therefore, we set the close flag for each socket and then call SignalSocketThread 
 353    // which will wake up the socket thread to close the sockets.
 354    for( INT32 i=0; i<g_Sockets_Driver.m_cntSockets; i++ )
 355    {
 356        SOCK_SOCKET sock = g_Sockets_Driver.m_socketHandles[i].m_socket;
 357        
 358        if((sock != SOCK_SOCKET_ERROR) && (fCloseDbg || !ISSET_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[i], SocketRegisterMap::c_DebugSocket)))
 359        {
 360            SET_SOCKET_FLAG( g_Sockets_Driver.m_socketHandles[i], SocketRegisterMap::c_CloseSocket );
 361        }
 362    }
 363
 364    HAL_SOCK_SignalSocketThread();
 365}
 366
 367//--//
 368
 369SOCK_SOCKET Sockets_Driver::Socket( INT32 family, INT32 type, INT32 protocol, BOOL fDebug )
 370{
 371    NATIVE_PROFILE_PAL_COM();
 372    SOCK_SOCKET ret = SOCK_SOCKET_ERROR;
 373    
 374    if(g_Sockets_Driver.m_cntSockets < (fDebug? SOCKETS_MAX_COUNT: SOCKETS_MAX_COUNT-1)) //leave one for the debugger
 375    {
 376        ret = HAL_SOCK_socket(family, type, protocol);
 377
 378        if(ret != SOCK_SOCKET_ERROR)
 379        {
 380            // TODO: because we are somewhat constrained by the number of sockets we support
 381            // we may want to force sockets to have linger set to 0 to force cleanup when they are closed.
 382            //INT32 optVal = 0;
 383            
 384            //HAL_SOCK_setsockopt(ret, SOCK_SOL_SOCKET, SOCK_SOCKO_LINGER, (const char*)&optVal, sizeof(INT32));
 385
 386            RegisterSocket(ret, (protocol != SOCK_IPPROTO_TCP), fDebug);
 387        }
 388    }
 389
 390    return ret;
 391}
 392INT32 Sockets_Driver::Connect(SOCK_SOCKET socket, const struct SOCK_sockaddr* address, INT32 addressLen)
 393{
 394    NATIVE_PROFILE_PAL_COM();
 395    INT32 ret = HAL_SOCK_connect(socket, address, addressLen);
 396
 397    // WARNING: the socket is selectable if the connect returns EWOULDBLOCK because the connection process has started,
 398    // the managed code portion polls for completion
 399    if((ret != SOCK_SOCKET_ERROR) || (HAL_SOCK_getlasterror() == SOCK_EWOULDBLOCK))
 400    {
 401        RegisterForSelect(socket);
 402    }
 403    return ret;
 404}
 405INT32 Sockets_Driver::Send(SOCK_SOCKET socket, const char* buf, INT32 len, INT32 flags) 
 406{
 407    NATIVE_PROFILE_PAL_COM();
 408    INT32 ret;
 409
 410    if(SOCK_FD_ISSET(socket, &g_Sockets_Driver.m_fdsetExcept)) return SOCK_SOCKET_ERROR;
 411
 412#if defined(SOCKETS_MAX_SEND_LENGTH)
 413    if((0 < SOCKETS_MAX_SEND_LENGTH) && (SOCKETS_MAX_SEND_LENGTH < len))
 414    {
 415        len = SOCKETS_MAX_SEND_LENGTH;
 416    }
 417#endif
 418    
 419    ret = HAL_SOCK_send(socket, buf, len, flags);
 420
 421    ClearStatusBit(socket, &g_Sockets_Driver.m_fdsetWrite);
 422
 423    return ret;
 424}
 425INT32 Sockets_Driver::Recv(SOCK_SOCKET socket, char* buf, INT32 len, INT32 flags)
 426{
 427    NATIVE_PROFILE_PAL_COM();
 428    char  c   = 0;
 429    INT32 ret = 0;
 430    
 431    if(SOCK_FD_ISSET(socket, &g_Sockets_Driver.m_fdsetExcept)) return SOCK_SOCKET_ERROR;
 432        
 433    ret = HAL_SOCK_recv(socket, buf, len, flags);
 434
 435    // only clear the status bit if we have no more data to read
 436    if(HAL_SOCK_recv(socket, &c, sizeof(c),  SOCKET_READ_PEEK_OPTION) < 0)
 437    {
 438        ClearStatusBit(socket, &g_Sockets_Driver.m_fdsetRead);
 439    }
 440    
 441    return ret;
 442}
 443
 444INT32 Sockets_Driver::Shutdown(SOCK_SOCKET sock, INT32 how)
 445{
 446    RegisterForSelect(sock, FALSE);
 447
 448    return HAL_SOCK_shutdown(sock, how);
 449}
 450
 451//-----------------------------------------------------------------------------
 452//
 453// Close - The close method marks a socket to be closed by the select thread.  Close is handled
 454// in this way because (at least for one implementation) the select method can not be set for a 
 455// closed socket.  Therfore in the select thread the socket is closed.
 456//
 457//-----------------------------------------------------------------------------
 458INT32 Sockets_Driver::Close(SOCK_SOCKET sock)
 459{
 460    NATIVE_PROFILE_PAL_COM();
 461    GLOBAL_LOCK_SOCKETS(x);
 462
 463    RegisterForSelect(sock, FALSE);
 464
 465    // For some platforms, we need to close the socket on a separate socket thread,
 466    // therefore, we set the close flag for each socket and then call SignalSocketThread 
 467    // which will wake up the socket thread to close the sockets.
 468    for(INT32 i=0; i<g_Sockets_Driver.m_cntSockets; i++)
 469    {
 470        if(g_Sockets_Driver.m_socketHandles[i].m_socket == sock)
 471        {
 472            SET_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[i], SocketRegisterMap::c_CloseSocket);
 473            break;
 474        }
 475    }
 476
 477    HAL_SOCK_SignalSocketThread();
 478
 479    return 0;        
 480}
 481INT32 Sockets_Driver::Listen( SOCK_SOCKET socket, INT32 backlog )
 482{
 483    NATIVE_PROFILE_PAL_COM();
 484    INT32 ret = HAL_SOCK_listen(socket, backlog);
 485
 486    // register the socket for select now that we are in listen mode
 487    RegisterForSelect(socket);
 488
 489    return ret;
 490}
 491SOCK_SOCKET Sockets_Driver::Accept( SOCK_SOCKET socket, struct SOCK_sockaddr* address, INT32* addressLen, BOOL fDebug )
 492{
 493    NATIVE_PROFILE_PAL_COM();
 494    SOCK_SOCKET ret = SOCK_SOCKET_ERROR;
 495
 496    if(g_Sockets_Driver.m_cntSockets < (fDebug? SOCKETS_MAX_COUNT: SOCKETS_MAX_COUNT-1)) //leave one for the debugger
 497    {
 498        ret = HAL_SOCK_accept(socket, address, addressLen);
 499
 500        if(ret != SOCK_SOCKET_ERROR)
 501        {
 502            RegisterSocket(ret, TRUE, fDebug);
 503        }    
 504
 505        ClearStatusBit(socket, &g_Sockets_Driver.m_fdsetRead);
 506    }
 507
 508    return ret;
 509}    
 510
 511INT32 Sockets_Driver::SetSelectValues( SOCK_fd_set *reqSet, SOCK_fd_set *selectSet, BOOL fClearIfSet )
 512{
 513    NATIVE_PROFILE_PAL_COM();
 514    INT32 cnt = 0;
 515    INT32 i;
 516
 517    if(reqSet != NULL)
 518    {
 519        for(i=0; i<reqSet->fd_count; i++ )
 520        {
 521            ///
 522            /// Check for invalid sockets first.  If any of the given sockets in reqSet are not valid sockets
 523            /// then we must return SOCKET_ERROR
 524            ///
 525            bool fErrs = true;
 526            for(int index = 0; index < g_Sockets_Driver.m_cntSockets; index++)
 527            {
 528                if(reqSet->fd_array[i] == g_Sockets_Driver.m_socketHandles[index].m_socket)
 529                {
 530                    fErrs = false;
 531                    break;
 532                }
 533            }
 534
 535            if(fErrs) return SOCK_SOCKET_ERROR;
 536
 537            if(SOCK_FD_ISSET(reqSet->fd_array[i], selectSet))
 538            {
 539                reqSet->fd_array[cnt] = reqSet->fd_array[i];
 540
 541                if(fClearIfSet)
 542                {
 543                    SOCK_FD_CLR(reqSet->fd_array[i], selectSet);
 544                }
 545
 546                cnt++;
 547            }
 548        }
 549        reqSet->fd_count = cnt;
 550    }
 551
 552    return cnt;
 553}
 554
 555// We maintain a current collection of the select results for all sockets.  This was done to support
 556// OS ports (NetOS).  We use the socket 'select' method as an asynchronous eventing system for socket activity.
 557INT32 Sockets_Driver::Select( INT32 nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* exceptfds, const SOCK_timeval* timeout )
 558{
 559    NATIVE_PROFILE_PAL_COM();
 560    INT32 cnt = 0;
 561    INT32 val = 0;
 562    
 563    GLOBAL_LOCK_SOCKETS(lock);
 564  
 565    if(SOCK_SOCKET_ERROR == (val = SetSelectValues( readfds  , &g_Sockets_Driver.m_fdsetRead,   FALSE ))) return SOCK_SOCKET_ERROR;
 566    cnt += val;
 567
 568    if(SOCK_SOCKET_ERROR == (val = SetSelectValues( writefds , &g_Sockets_Driver.m_fdsetWrite,  FALSE ))) return SOCK_SOCKET_ERROR;
 569    cnt += val;
 570
 571    if(SOCK_SOCKET_ERROR == (val = SetSelectValues( exceptfds, &g_Sockets_Driver.m_fdsetExcept, TRUE  ))) return SOCK_SOCKET_ERROR;
 572    cnt += val;
 573
 574    return cnt;
 575}
 576INT32 Sockets_Driver::RecvFrom( SOCK_SOCKET s, char* buf, INT32 len, INT32 flags, struct SOCK_sockaddr* from, INT32* fromlen )
 577{
 578    NATIVE_PROFILE_PAL_COM();
 579    char c = 0;
 580    INT32 ret = 0;
 581
 582    if(SOCK_FD_ISSET(s, &g_Sockets_Driver.m_fdsetExcept)) return SOCK_SOCKET_ERROR;
 583        
 584    ret = HAL_SOCK_recvfrom(s, buf, len, flags, from, fromlen);
 585
 586    // only clear the status bit if we have no more data to read
 587    if(HAL_SOCK_recvfrom(s, &c, sizeof(c),  SOCKET_READ_PEEK_OPTION, from, fromlen) < 0)
 588    {
 589        ClearStatusBit(s, &g_Sockets_Driver.m_fdsetRead);
 590    }
 591
 592    return ret;
 593}
 594INT32 Sockets_Driver::SendTo( SOCK_SOCKET s, const char* buf, INT32 len, INT32 flags, const struct SOCK_sockaddr* to, INT32 tolen )
 595{
 596    NATIVE_PROFILE_PAL_COM();
 597    INT32 ret;
 598
 599    if(SOCK_FD_ISSET(s, &g_Sockets_Driver.m_fdsetExcept)) return SOCK_SOCKET_ERROR;
 600    
 601#if defined(SOCKETS_MAX_SEND_LENGTH)
 602    if((0 < SOCKETS_MAX_SEND_LENGTH) && (SOCKETS_MAX_SEND_LENGTH < len))
 603    {
 604        len = SOCKETS_MAX_SEND_LENGTH;
 605    }
 606#endif
 607    
 608    ret = HAL_SOCK_sendto(s, buf, len, flags, to, tolen);
 609
 610    ClearStatusBit(s, &g_Sockets_Driver.m_fdsetWrite);
 611
 612    return ret;
 613}
 614
 615
 616//--//
 617
 618//-----------------------------------------------------------------------------
 619//
 620//  MulticastDiscoveryRespond - Respond to a NETMF multicast message.  This is
 621//  a simple discovery mechanism that uses multicast sockets over UDP.  The
 622//  client will send a message to the ip address defined by
 623//     SOCK_DISCOVERY_MULTICAST_IPADDR 
 624//  over port
 625//     SOCK_DISCOVERY_MULTICAST_PORT
 626//  If the message contains the sting "NETMF", then a response is sent with the
 627//  the data structure SOCK_discoveryinfo (which includes the ip address and mac
 628//  address of the device).
 629//
 630//-----------------------------------------------------------------------------
 631void Sockets_Driver::MulticastDiscoveryRespond()
 632{
 633    NATIVE_PROFILE_PAL_COM();
 634    SOCK_sockaddr from;
 635
 636    char data[64];
 637    INT32 fromlen = sizeof(from);
 638
 639    // intentionally call the HAL recvfrom so as not to invoke the signalnotifythread
 640    INT32 len = HAL_SOCK_recvfrom( g_Sockets_Driver.m_multicastSocket, data, sizeof(data), 0, &from, &fromlen );
 641
 642    if(len > 0)
 643    {
 644        UINT32 idx = 0;
 645        BOOL fFound = FALSE;
 646        const char* c_Signature = SOCK_DISCOVERY_MULTICAST_TOKEN;
 647        INT32 sigLen = hal_strlen_s(c_Signature);
 648
 649        // search for discovery token
 650        while(idx <= (len-sigLen))
 651        {
 652            if(0 == memcmp( &data[idx], c_Signature, sigLen))
 653            {
 654                fFound = TRUE;
 655                break;
 656            }
 657            idx++;
 658        }
 659        
 660        if(fFound)
 661        {
 662            SOCK_NetworkConfiguration current;
 663            SOCK_discoveryinfo info;
 664            SOCK_sockaddr_in sockAddr;
 665            SOCK_sockaddr_in sockAddrMulticast;
 666            INT32 opt = 64;
 667            SOCK_SOCKET sock;
 668            INT32 nonblocking = 1;
 669
 670            // Load is required here because the g_NetworkConfig contains only the static ip address (not DHCP)
 671            HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(0, &current);
 672
 673            info.ipaddr        = current.ipaddr;
 674            info.macAddressLen = current.macAddressLen;
 675            memcpy( &info.macAddressBuffer[0], &current.macAddressBuffer[0], current.macAddressLen );
 676
 677            sock = Socket(SOCK_AF_INET, SOCK_SOCK_DGRAM, SOCK_IPPROTO_UDP, FALSE);
 678            SOCKET_CHECK_RESULT(sock);
 679
 680            memset( &sockAddr, 0, sizeof(sockAddr) );
 681            sockAddr.sin_family           = SOCK_AF_INET;
 682            sockAddr.sin_port             = SOCK_htons(0);
 683            sockAddr.sin_addr.S_un.S_addr = info.ipaddr;
 684
 685            memset( &sockAddrMulticast, 0, sizeof(sockAddrMulticast) );
 686            sockAddrMulticast.sin_family           = SOCK_AF_INET;
 687            sockAddrMulticast.sin_port             = SOCK_htons(SOCK_DISCOVERY_MULTICAST_PORT);
 688            sockAddrMulticast.sin_addr.S_un.S_addr = SOCK_htonl(SOCK_DISCOVERY_MULTICAST_IPADDR_SND);
 689
 690            SOCKET_CHECK_RESULT(HAL_SOCK_ioctl(sock, SOCK_FIONBIO, &nonblocking));
 691            SOCKET_CHECK_RESULT(HAL_SOCK_setsockopt(sock, SOCK_IPPROTO_IP, SOCK_IPO_MULTICAST_TTL, (const char *) &opt, sizeof(opt)));
 692            SOCKET_CHECK_RESULT(HAL_SOCK_bind(sock,  (SOCK_sockaddr*)&sockAddr, sizeof(sockAddr)));
 693            // send a multicast socket back to the caller
 694            SOCKET_CHECK_RESULT(SendTo(sock, (const char*)&info, sizeof(info), 0, (SOCK_sockaddr*)&sockAddrMulticast, sizeof(sockAddrMulticast)));
 695
 696            SOCK_close(sock);
 697
 698            SOCKET_CLEANUP();
 699
 700            if(sock != SOCK_SOCKET_ERROR)
 701            {
 702                SOCK_close(sock);
 703
 704                debug_printf("MULTICAST RESP SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() );
 705            }
 706
 707            SOCKET_CHECK_EXIT_NORETURN();            
 708        }
 709    }
 710}
 711
 712//-----------------------------------------------------------------------------
 713//
 714// WaitForEventThread - socket activity monitor thread function
 715//   This method is used as a monitor thread for the socket subsystem.  It waits
 716//   for activity by calling the select method for each open (selectable) socket.
 717//   In order to prevent spinning when a socket is in an evented state, we update
 718//   a global fd_set for read/write/except.  Then when a caller invokes the 
 719//   select method it will use the global state rather than calling select.
 720//
 721//-----------------------------------------------------------------------------
 722BOOL Sockets_Driver::ProcessSocketActivity(SOCK_SOCKET signalSocket)
 723{
 724    NATIVE_PROFILE_PAL_COM();
 725    SOCK_fd_set rCpy;
 726    SOCK_fd_set wCpy;
 727    SOCK_fd_set eCpy;
 728
 729    SOCK_timeval timeout;
 730
 731    timeout.tv_sec  = 0;
 732    timeout.tv_usec = 0;
 733
 734    INT32 sel = 0;
 735    bool fSockClosed = false;
 736
 737    if(signalSocket != SOCK_SOCKET_ERROR) SOCK_FD_SET( signalSocket, &g_Sockets_Driver.m_nextReadSet );
 738    
 739    // always select multicast socket
 740    if(g_Sockets_Driver.m_multicastSocket != SOCK_SOCKET_ERROR) SOCK_FD_SET( g_Sockets_Driver.m_multicastSocket, &g_Sockets_Driver.m_nextReadSet );
 741
 742    // NULL timeout uses largest ulong value, thus creating a blocking call
 743    sel = HAL_SOCK_select( SOCK_FD_SETSIZE, &g_Sockets_Driver.m_nextReadSet, &g_Sockets_Driver.m_nextWriteSet, &g_Sockets_Driver.m_nextExcptSet, &timeout);
 744
 745    if(SOCK_SOCKET_ERROR == sel)
 746    {
 747        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextReadSet);
 748        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextWriteSet);
 749        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextExcptSet);
 750    }
 751    // always process (incase there are any closed sockets)
 752    {
 753        // the update lock mutex is used to safely modify the global
 754        GLOBAL_LOCK_SOCKETS(lock);
 755
 756        // clear out the temp fd_set variables
 757        SOCK_FD_ZERO(&rCpy);  
 758        SOCK_FD_ZERO(&wCpy); 
 759        SOCK_FD_ZERO(&eCpy); 
 760
 761        // loop through each open socket and determine which ones need to be set
 762        // for the next select call.  Note sockets that already have events in the
 763        // global state do not need (AND SHOULDN'T) to be added to the next select call.
 764        for(INT32 i=0; i<g_Sockets_Driver.m_cntSockets; i++)
 765        {
 766            if(ISSET_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[i], SocketRegisterMap::c_CloseSocket))
 767            {
 768                SOCK_SOCKET s = g_Sockets_Driver.m_socketHandles[i].m_socket;
 769
 770                if(g_Sockets_Driver.m_socketHandles[i].m_sslData == NULL)
 771                {
 772                    // g_Sockets_Driver.m_socketHandles[i] is no longer valid after this call
 773                    UnregisterSocket(i); 
 774
 775                    if(SOCK_SOCKET_ERROR == HAL_SOCK_close(s))
 776                    {
 777                        debug_printf("ERROR: HAL_SOCK_close: %d\r\n", HAL_SOCK_getlasterror());
 778                    }
 779
 780                }
 781                // c_SSL_DATA_SOCKET_CLOSED_BY_SSL indicates the socket already closed by SSL
 782                else
 783                {
 784
 785                    // SSL_CloseSocket calls UnregisterSocket
 786                    SSL_CloseSocket(s);
 787                }
 788
 789                fSockClosed = true;
 790
 791                i--; continue; // Unregister socket collapses the array, so try again with previous 'i' value                    
 792            }
 793
 794            // sockets must be in a connected or listening state before they can be added to the
 795            // select method
 796            if(!ISSET_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[i], SocketRegisterMap::c_SelectableSocket))
 797            {
 798                continue;
 799            }
 800
 801            SOCK_SOCKET sock = g_Sockets_Driver.m_socketHandles[i].m_socket;
 802
 803            
 804            if(sel > 0)
 805            {
 806                // update the global fd_set variables if we have activity on any socket (DO THIS BEFORE UPDATING THE NEXT SELECT SETS)
 807                if(SOCK_FD_ISSET(sock, &g_Sockets_Driver.m_nextReadSet))
 808                {
 809                    SOCK_FD_SET( sock, &g_Sockets_Driver.m_fdsetRead );
 810                }
 811                if(SOCK_FD_ISSET(sock, &g_Sockets_Driver.m_nextWriteSet))
 812                {
 813                    SOCK_FD_SET( sock, &g_Sockets_Driver.m_fdsetWrite );
 814                }
 815                if(SOCK_FD_ISSET(sock, &g_Sockets_Driver.m_nextExcptSet))
 816                {
 817                    SOCK_FD_SET( sock, &g_Sockets_Driver.m_fdsetExcept );
 818                }
 819            }
 820            // only update the select sockets if they don't exist in the global fd_set variables
 821            // MAKE SURE THIS IS DONE AFTER UPDATING THE GLOBAL STATE (above)
 822            if(!SOCK_FD_ISSET(sock, &g_Sockets_Driver.m_fdsetRead ))
 823            {
 824                SOCK_FD_SET( sock, &rCpy );
 825            }
 826            if(!SOCK_FD_ISSET(sock, &g_Sockets_Driver.m_fdsetWrite ))
 827            {
 828                SOCK_FD_SET( sock, &wCpy );
 829            }
 830            if(!SOCK_FD_ISSET(sock, &g_Sockets_Driver.m_fdsetExcept ))
 831            {
 832                SOCK_FD_SET( sock, &eCpy );
 833            }
 834        }
 835
 836        if(sel > 0 && SOCK_FD_ISSET( g_Sockets_Driver.m_multicastSocket, &g_Sockets_Driver.m_nextReadSet ))
 837        {
 838            MulticastDiscoveryRespond();
 839            sel--;
 840        }
 841        
 842        // copy over the temp fd_set variables
 843        memcpy( &g_Sockets_Driver.m_nextReadSet , &rCpy, sizeof(rCpy) );
 844        memcpy( &g_Sockets_Driver.m_nextWriteSet, &wCpy, sizeof(wCpy) );
 845        memcpy( &g_Sockets_Driver.m_nextExcptSet, &eCpy, sizeof(eCpy) );
 846
 847        if((sel > 0 || fSockClosed) && !g_Sockets_Driver.m_fShuttingDown)
 848        {
 849            HAL_SOCK_EventsSet( SOCKET_EVENT_FLAG_SOCKET );
 850        }
 851    }
 852
 853    return TRUE;
 854}
 855
 856BOOL Sockets_Driver::InitializeDbgListener( int ComPortNum )
 857{   
 858    NATIVE_PROFILE_PAL_COM();
 859    SOCK_sockaddr_in sockAddr;
 860    INT32 nonblocking = 1;
 861    INT32 optval = 1;
 862    INT32 optLinger = 0;
 863    SOCKET_CHECK_ENTER();
 864
 865    if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return FALSE;
 866
 867    if(g_Sockets_Driver.m_SocketDebugListener != SOCK_SOCKET_ERROR) return TRUE;
 868
 869    s_DebuggerTimeoutCompletion.InitializeForUserMode(OnDebuggerTimeout);
 870
 871    GLOBAL_LOCK_SOCKETS(sock);
 872
 873    //-- debug api socket --//
 874
 875    g_Sockets_Driver.m_SocketDebugListener = Socket( SOCK_AF_INET, SOCK_SOCK_STREAM, SOCK_IPPROTO_TCP, TRUE );
 876    SOCKET_CHECK_RESULT( g_Sockets_Driver.m_SocketDebugListener );
 877
 878    memset( &sockAddr, 0, sizeof(sockAddr) );
 879    sockAddr.sin_family             = SOCK_AF_INET;
 880    sockAddr.sin_port               = SOCK_htons(DEBUG_SOCKET_PORT);
 881    sockAddr.sin_addr.S_un.S_addr   = SOCK_htonl(SOCK_INADDR_ANY);
 882
 883    SOCKET_CHECK_RESULT( SOCK_ioctl(g_Sockets_Driver.m_SocketDebugListener, SOCK_FIONBIO, &nonblocking) );
 884
 885    SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt( g_Sockets_Driver.m_SocketDebugListener, SOCK_IPPROTO_TCP, SOCK_TCP_NODELAY, (char*)&optval, sizeof(optval) ) );
 886
 887    SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt(g_Sockets_Driver.m_SocketDebugListener, SOCK_SOL_SOCKET, SOCK_SOCKO_LINGER, (const char*)&optLinger, sizeof(INT32)) );
 888
 889    SOCKET_CHECK_RESULT( SOCK_bind( g_Sockets_Driver.m_SocketDebugListener,  (SOCK_sockaddr*)&sockAddr, sizeof(sockAddr) ) );
 890
 891    SOCKET_CHECK_RESULT( SOCK_listen( g_Sockets_Driver.m_SocketDebugListener, 1 ) );
 892
 893    g_Sockets_Driver.m_stateDebugSocket = DbgSock_Listening;
 894
 895    Sockets_Driver::InitializeMulticastDiscovery();
 896
 897    SOCKET_CLEANUP();
 898
 899    if(g_Sockets_Driver.m_SocketDebugListener != SOCK_SOCKET_ERROR)
 900    {
 901        SOCK_close(g_Sockets_Driver.m_SocketDebugListener);
 902        g_Sockets_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR;
 903
 904        debug_printf("DBGLISTENER SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() );
 905    }
 906
 907    SOCKET_CHECK_EXIT_BOOL_CLEANUP();
 908}
 909
 910BOOL Sockets_Driver::UninitializeDbgListener( int ComPortNum )
 911{
 912    NATIVE_PROFILE_PAL_COM();
 913
 914    if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return FALSE;
 915
 916    g_Sockets_Driver.m_stateDebugSocket = DbgSock_Uninitialized;
 917    
 918    GLOBAL_LOCK_SOCKETS(lock);
 919
 920    CloseDebuggerSocket();
 921
 922    if(g_Sockets_Driver.m_SocketDebugListener != SOCK_SOCKET_ERROR)
 923    {
 924        SOCK_close( g_Sockets_Driver.m_SocketDebugListener );
 925        g_Sockets_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR;
 926    }
 927
 928    return TRUE;
 929}
 930
 931void Sockets_Driver::SaveConfig(INT32 index, SOCK_NetworkConfiguration *cfg)
 932{
 933    NATIVE_PROFILE_PAL_COM();
 934    if(index >= NETWORK_INTERFACE_COUNT) return;
 935
 936    if(cfg) 
 937    {
 938        memcpy( &g_NetworkConfig.NetworkInterfaces[index], cfg, sizeof(SOCK_NetworkConfiguration) );
 939    }
 940    
 941    HAL_CONFIG_BLOCK::UpdateBlockWithName(g_NetworkConfig.GetDriverName(), &g_NetworkConfig, sizeof(g_NetworkConfig), TRUE);
 942}
 943
 944void Sockets_Driver::ApplyConfig()
 945{
 946    NATIVE_PROFILE_PAL_COM();
 947    if(!HAL_CONFIG_BLOCK::ApplyConfig( g_NetworkConfig.GetDriverName(), &g_NetworkConfig, sizeof(g_NetworkConfig) ))
 948    {
 949        // save to the dynamic config section so that MFDeploy will be able to get the configuration.
 950        SaveConfig(0, NULL);            
 951    }
 952}
 953
 954void Sockets_Driver::ApplyWirelessConfig()
 955{
 956    NATIVE_PROFILE_PAL_COM();
 957
 958    if(!s_wirelessInitialized)
 959    {
 960        if(!HAL_CONFIG_BLOCK::ApplyConfig( g_WirelessConfig.GetDriverName(), &g_WirelessConfig, sizeof(g_WirelessConfig) ))
 961        {
 962            SaveWirelessConfig(0, NULL);
 963        }
 964        s_wirelessInitialized = TRUE;
 965    }
 966}
 967
 968void Sockets_Driver::SaveWirelessConfig(INT32 index, SOCK_NetworkConfiguration *cfg)
 969{
 970    NATIVE_PROFILE_PAL_COM();
 971    if(index >= WIRELESS_INTERFACE_COUNT) return;
 972    
 973    if(cfg) 
 974    {
 975        memcpy( &g_WirelessConfig.WirelessInterfaces[index], cfg, sizeof(SOCK_WirelessConfiguration) );
 976    }
 977    
 978    HAL_CONFIG_BLOCK::UpdateBlockWithName(g_WirelessConfig.GetDriverName(), &g_WirelessConfig, sizeof(g_WirelessConfig), TRUE);    
 979}
 980
 981
 982//-----------------------------------------------------------------------------
 983//
 984//  InitializeMulticastDiscovery - Initialize the NETMF discovery service for
 985//  sockets.  We use multicast sockets to create the discovery mechanism.   
 986//
 987//-----------------------------------------------------------------------------
 988BOOL Sockets_Driver::InitializeMulticastDiscovery()
 989{
 990    NATIVE_PROFILE_PAL_COM();
 991    SOCKET_CHECK_ENTER(); 
 992    SOCK_sockaddr_in sockAddr;
 993    INT32 nonblocking = 1;
 994
 995    if(g_Sockets_Driver.s_discoveryInitialized) return TRUE;
 996
 997    // set up discovery socket to list to defined discovery port for any ip address
 998    memset( &sockAddr, 0, sizeof(sockAddr) );
 999    sockAddr.sin_family           = SOCK_AF_INET;
1000    sockAddr.sin_port             = SOCK_htons(SOCK_DISCOVERY_MULTICAST_PORT);
1001    sockAddr.sin_addr.S_un.S_addr = SOCK_htonl(SOCK_INADDR_ANY);
1002
1003    // UDP socket is easier in our scenario because it isn't session based
1004    g_Sockets_Driver.m_multicastSocket = Socket( SOCK_AF_INET, SOCK_SOCK_DGRAM, SOCK_IPPROTO_UDP, TRUE );
1005    SOCKET_CHECK_RESULT( g_Sockets_Driver.m_multicastSocket );
1006
1007    // set sock option for multicast
1008    SOCK_ip_mreq multicast;
1009    multicast.imr_multiaddr.S_un.S_addr = SOCK_htonl(SOCK_DISCOVERY_MULTICAST_IPADDR);
1010    multicast.imr_interface.S_un.S_addr = SOCK_htonl(SOCK_INADDR_ANY);
1011
1012    SOCKET_CHECK_RESULT( SOCK_ioctl(g_Sockets_Driver.m_multicastSocket, SOCK_FIONBIO, &nonblocking) );
1013
1014    SOCKET_CHECK_RESULT( SOCK_setsockopt( g_Sockets_Driver.m_multicastSocket, SOCK_IPPROTO_IP, SOCK_IPO_ADD_MEMBERSHIP, (const char*)&multicast, sizeof(multicast) ) );
1015
1016    SOCKET_CHECK_RESULT( SOCK_bind( g_Sockets_Driver.m_multicastSocket, (SOCK_sockaddr*)&sockAddr, sizeof(sockAddr) ) );
1017
1018    g_Sockets_Driver.s_discoveryInitialized = TRUE;
1019
1020    SOCKET_CLEANUP()
1021
1022    if(g_Sockets_Driver.m_multicastSocket != SOCK_SOCKET_ERROR)
1023    {
1024        SOCK_close(g_Sockets_Driver.m_multicastSocket);
1025        g_Sockets_Driver.m_multicastSocket = SOCK_SOCKET_ERROR;
1026
1027        debug_printf("MULTICAST SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() );
1028    }
1029
1030    SOCKET_CHECK_EXIT_BOOL_CLEANUP();
1031}
1032
1033BOOL Sockets_Driver::Initialize()
1034{
1035    NATIVE_PROFILE_PAL_COM();
1036    SOCKET_CHECK_ENTER(); 
1037
1038    
1039    if(!s_initialized)
1040    {
1041        g_Sockets_Driver.m_fShuttingDown = FALSE;
1042
1043        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextReadSet);  
1044        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextWriteSet); 
1045        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextExcptSet); 
1046
1047        SOCK_FD_ZERO(&g_Sockets_Driver.m_fdsetRead);
1048        SOCK_FD_ZERO(&g_Sockets_Driver.m_fdsetWrite);
1049        SOCK_FD_ZERO(&g_Sockets_Driver.m_fdsetExcept);
1050
1051        g_Sockets_Driver.m_cntSockets = 0;
1052
1053        for( INT32 i=0; i<SOCKETS_MAX_COUNT; i++ )
1054        {
1055            g_Sockets_Driver.m_socketHandles[i].m_socket  = SOCK_SOCKET_ERROR;
1056            g_Sockets_Driver.m_socketHandles[i].m_flags   = 0;
1057            g_Sockets_Driver.m_socketHandles[i].m_sslData = NULL;
1058        }
1059
1060        g_Sockets_Driver.m_multicastSocket     = SOCK_SOCKET_ERROR;
1061        g_Sockets_Driver.m_SocketDebugStream   = SOCK_SOCKET_ERROR;
1062        g_Sockets_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR;
1063
1064        g_Sockets_Driver.m_stateDebugSocket = DbgSock_Uninitialized;
1065
1066        ApplyConfig();        
1067        ApplyWirelessConfig();
1068        
1069        SOCKET_CHECK_BOOL( HAL_SOCK_Initialize() );
1070
1071        if(!InitializeMulticastDiscovery())
1072        {
1073            debug_printf("MULTICAST discovery failed\r\n");
1074        }
1075
1076        HAL_SOCK_EventsSet(SOCKET_EVENT_FLAG_SOCKETS_READY);
1077
1078        //SOCKET_CHECK_BOOL( InitializeDbgListener() );
1079
1080        SSL_Initialize();
1081
1082        s_initialized = TRUE;
1083    }
1084     
1085    
1086    SOCKET_CHECK_EXIT_BOOL();
1087}
1088
1089BOOL Sockets_Driver::Uninitialize( )
1090{
1091    NATIVE_PROFILE_PAL_COM();
1092    BOOL ret = TRUE;
1093   
1094    if(s_initialized)
1095    {
1096        g_Sockets_Driver.m_stateDebugSocket = DbgSock_Uninitialized;
1097
1098        // close all connections (including debugger sockets)
1099        CloseConnections(TRUE);
1100
1101        SSL_Uninitialize();
1102    
1103        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextReadSet);  
1104        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextWriteSet); 
1105        SOCK_FD_ZERO(&g_Sockets_Driver.m_nextExcptSet); 
1106
1107        SOCK_FD_ZERO(&g_Sockets_Driver.m_fdsetRead);
1108        SOCK_FD_ZERO(&g_Sockets_Driver.m_fdsetWrite);
1109        SOCK_FD_ZERO(&g_Sockets_Driver.m_fdsetExcept);
1110
1111        g_Sockets_Driver.m_cntSockets = 0;
1112
1113        for( INT32 i=0; i<SOCKETS_MAX_COUNT; i++ )
1114        {
1115            g_Sockets_Driver.m_socketHandles[i].m_socket  = SOCK_SOCKET_ERROR;
1116            g_Sockets_Driver.m_socketHandles[i].m_flags   = 0;
1117            g_Sockets_Driver.m_socketHandles[i].m_sslData = NULL;
1118        }
1119
1120        g_Sockets_Driver.m_multicastSocket     = SOCK_SOCKET_ERROR;
1121        g_Sockets_Driver.m_SocketDebugStream   = SOCK_SOCKET_ERROR;
1122        g_Sockets_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR;
1123
1124        ret = HAL_SOCK_Uninitialize();
1125
1126        s_initialized          = FALSE;
1127        s_discoveryInitialized = FALSE;
1128        s_wirelessInitialized  = FALSE;
1129    }
1130   
1131    
1132    return ret;
1133}
1134
1135
1136static UINT64 s_lastWrite = 0;
1137
1138//-----------------------------------------------------------------------------
1139//
1140//  Write - The Write method will write data to the debugger stream socket (if a connection is active).
1141//  In addition if the write fails for a reason other than EWOULDBLOCK then we should shutdown
1142//  the debugger stream socket and change to the listening state
1143//
1144//-----------------------------------------------------------------------------
1145INT32 Sockets_Driver::Write( int ComPortNum, const char* Data, size_t size )
1146{
1147    NATIVE_PROFILE_PAL_COM();
1148    INT32 ret;
1149
1150    if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return SOCK_SOCKET_ERROR;
1151
1152    if((g_Sockets_Driver.m_stateDebugSocket  != DbgSock_Connected) ||
1153       (g_Sockets_Driver.m_SocketDebugStream == SOCK_SOCKET_ERROR)) 
1154    {
1155        return SOCK_SOCKET_ERROR;
1156    }
1157
1158    // the network stack (RTIP) can get overloaded with "hal_printf" messages which causes
1159    // the communication link to be killed (by sending a QUENCH message).  We have to add
1160    // an artificial delay here if the back-to-back writes are too close.
1161    UINT64 tics = HAL_Time_CurrentTicks();
1162    UINT64 cmp = (CPU_MillisecondsToTicks((UINT32)5) / 10) + 1; // at least 500 uSec
1163    if(((tics - s_lastWrite) < cmp))
1164    {
1165        // we can't sleep if the interrupts are off, so return
1166        if(!INTERRUPTS_ENABLED_STATE()) return 0;
1167        
1168        Events_WaitForEvents(0, 5);
1169    }
1170
1171    ret = SOCK_send( g_Sockets_Driver.m_SocketDebugStream, Data, size, 0 );
1172
1173    if(ret < 0) 
1174    {
1175        INT32 err = HAL_SOCK_getlasterror();
1176
1177        // debugger stream is no longer active, change to listening state
1178        if(err != SOCK_EWOULDBLOCK)
1179        {
1180            CloseDebuggerSocket();
1181        }
1182        else
1183        {   
1184            ret = 0;
1185        }
1186    }
1187    else
1188    {
1189        s_lastWrite = HAL_Time_CurrentTicks();
1190    }
1191
1192    return ret;
1193}
1194
1195//-----------------------------------------------------------------------------
1196//
1197//  Read - the Read method performs two duties: first to read data from the debug stream; and 
1198//  second to manage the debugger connection state.  The initial state is to be listening for debug
1199//  connections, and therefore each read performs an accept to see if there is a pending connection.
1200//  Once a connection is made the state changes to connected and the debugger stream socket 
1201//  is read for each Read call.  During the Connected state an Accept is still called so that no other 
1202//  connections will be handled.  If the debugger is still receiving data on the debugger stream, then
1203//  new connections will be closed immediately.  If the debugger stream socket has been closed then
1204//  the state return to the listening state (unless there is an pending connection in which case the 
1205//  pending connection becomes the new debugger stream).
1206//
1207//-----------------------------------------------------------------------------
1208INT32 Sockets_Driver::Read( int ComPortNum, char* Data, size_t size )
1209{
1210    NATIVE_PROFILE_PAL_COM();
1211    SOCK_SOCKET sock;
1212    SOCK_sockaddr_in addr;
1213    INT32 len = sizeof(addr);
1214    INT32 ret = 0;
1215
1216    if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return 0;
1217
1218    if(g_Sockets_Driver.m_stateDebugSocket == DbgSock_Uninitialized) return 0;
1219
1220    memset(&addr, 0, sizeof(addr));
1221
1222    // if we are connected, then read from the debug stream
1223    if(g_Sockets_Driver.m_stateDebugSocket == DbgSock_Connected)
1224    {
1225        ret = SOCK_recv(g_Sockets_Driver.m_SocketDebugStream, Data, size, 0);
1226
1227        // return value of zero indicates a shutdown of the socket.  Also we shutdown for any error except
1228        // ewouldblock.  If either of these happens, then we go back to the listening state
1229        if((ret == 0) || (ret == SOCK_SOCKET_ERROR && HAL_SOCK_getlasterror() != SOCK_EWOULDBLOCK))
1230        {
1231            CloseDebuggerSocket();
1232        }
1233        else if(ret != SOCK_SOCKET_ERROR && s_DebuggerTimeoutCompletion.IsLinked())
1234        {
1235            // we either got data or the socket was closed, so kill the timeout
1236            s_DebuggerTimeoutCompletion.Abort();
1237        }
1238    }
1239
1240    // we always perform an accept so that we handle pending connections
1241    // if we alread are connected and the debug stream socket is still active, then we immediately close
1242    // the pending connection
1243    sock = Accept( g_Sockets_Driver.m_SocketDebugListener, (SOCK_sockaddr*)&addr, &len, TRUE );
1244
1245    if(SOCK_SOCKET_ERROR != sock)
1246    {
1247        INT32 nonblocking = 1;
1248        BOOL  optval      = 1;
1249        INT32 optLinger   = 0;
1250
1251        GLOBAL_LOCK_SOCKETS(lock);
1252
1253        // if we are already in the connected state, then verify that the debugger stream socket is still active
1254        if(DbgSock_Connected == g_Sockets_Driver.m_stateDebugSocket)
1255        {
1256            // the debugger stream is still active, so shutdown the pending connection
1257            HAL_SOCK_setsockopt( sock, SOCK_SOL_SOCKET, SOCK_SOCKO_LINGER, (const char*)&optLinger, sizeof(INT32) );
1258            SOCK_close(sock);
1259
1260            // set timeout since another connection is trying to use us.
1261            if(!s_DebuggerTimeoutCompletion.IsLinked())
1262            {
1263                s_DebuggerTimeoutCompletion.EnqueueDelta(5000000); // 5 seconds
1264            }
1265        }
1266        else // we are in the listening state, so accept the pending connection and update the state
1267        {
1268            g_Sockets_Driver.m_SocketDebugStream = sock;
1269            SOCKET_CHECK_RESULT( SOCK_ioctl(g_Sockets_Driver.m_SocketDebugStream, SOCK_FIONBIO, &nonblocking) );
1270            SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt( g_Sockets_Driver.m_SocketDebugStream, SOCK_IPPROTO_TCP, SOCK_TCP_NODELAY, (char*)&optval, sizeof(optval) ) );
1271            SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt( g_Sockets_Driver.m_SocketDebugStream, SOCK_SOL_SOCKET, SOCK_SOCKO_LINGER, (const char*)&optLinger, sizeof(INT32) ) );
1272
1273            g_Sockets_Driver.m_stateDebugSocket = DbgSock_Connected;
1274
1275            SOCKET_CLEANUP()
1276
1277            if(g_Sockets_Driver.m_SocketDebugStream != SOCK_SOCKET_ERROR)
1278            {
1279                SOCK_close(g_Sockets_Driver.m_SocketDebugStream);
1280                g_Sockets_Driver.m_SocketDebugStream = SOCK_SOCKET_ERROR;
1281
1282                debug_printf("DBGSTREAM SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() );
1283            }
1284
1285            SOCKET_CHECK_EXIT_NORETURN();
1286        }
1287        
1288        HAL_SOCK_EventsSet( SOCKET_EVENT_FLAG_SOCKET );
1289    }
1290
1291
1292    if(ret < 0)
1293    {  
1294        ret = 0;
1295    }
1296
1297    return ret;
1298}
1299
1300
1301//-----------------------------------------------------------------------------
1302//
1303//  ClearStatusBit - this method is used to remove the given socket from the given set
1304//  It is only used with the global read,write,except sets.  When the operation is complete
1305//  the select thread is notified so that it can update the select state.
1306//
1307//-----------------------------------------------------------------------------
1308void Sockets_Driver::ClearStatusBit( SOCK_SOCKET sock, SOCK_fd_set *fdset )
1309{
1310    NATIVE_PROFILE_PAL_COM();
1311    GLOBAL_LOCK_SOCKETS(lock);
1312
1313    if(SOCK_FD_ISSET(sock, fdset))
1314    {
1315        SOCK_FD_CLR( sock, fdset );
1316    }
1317    HAL_SOCK_SignalSocketThread();
1318}
1319
1320void Sockets_Driver::ClearStatusBitsForSocket(SOCK_SOCKET sock, BOOL fWrite)
1321{
1322    GLOBAL_LOCK_SOCKETS(lock);
1323
1324    if(fWrite && SOCK_FD_ISSET( sock, &g_Sockets_Driver.m_fdsetWrite ))
1325    {
1326        SOCK_FD_CLR( sock, &g_Sockets_Driver.m_fdsetWrite );
1327    }
1328    if(!fWrite && SOCK_FD_ISSET( sock, &g_Sockets_Driver.m_fdsetRead ))
1329    {
1330        SOCK_FD_CLR( sock, &g_Sockets_Driver.m_fdsetRead );
1331    }
1332    if(SOCK_FD_ISSET( sock, &g_Sockets_Driver.m_fdsetExcept ))
1333    {
1334        SOCK_FD_CLR( sock, &g_Sockets_Driver.m_fdsetExcept );
1335    }
1336    HAL_SOCK_SignalSocketThread();
1337}
1338
1339//-----------------------------------------------------------------------------
1340//
1341//  RegisterForSelect - this method is used to register a socket for selection
1342//    or ethernet activity.  A socket can only be included in the select if it 
1343//    is in a connected or listening state.
1344//
1345//-----------------------------------------------------------------------------
1346void Sockets_Driver::RegisterForSelect( SOCK_SOCKET sock, BOOL isSelectable )
1347{
1348    NATIVE_PROFILE_PAL_COM();
1349    if(sock == SOCK_SOCKET_ERROR) 
1350    {
1351        ASSERT(FALSE);
1352        return;
1353    }
1354
1355    GLOBAL_LOCK_SOCKETS(lock);
1356
1357    for(INT32 i=0; i<g_Sockets_Driver.m_cntSockets; i++)
1358    {
1359        if(sock == g_Sockets_Driver.m_socketHandles[i].m_socket)
1360        {
1361            if(isSelectable)
1362            {
1363                SET_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[i], SocketRegisterMap::c_SelectableSocket);
1364            }
1365            else
1366            {
1367                CLEAR_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[i], SocketRegisterMap::c_SelectableSocket);
1368            }
1369            break;
1370        }
1371    }
1372
1373    if(isSelectable)
1374    {
1375        SOCK_FD_SET(sock, &g_Sockets_Driver.m_nextReadSet);
1376        SOCK_FD_SET(sock, &g_Sockets_Driver.m_nextWriteSet);
1377        SOCK_FD_SET(sock, &g_Sockets_Driver.m_nextExcptSet);
1378    }
1379    else
1380    {
1381        SOCK_FD_CLR(sock, &g_Sockets_Driver.m_fdsetRead  ); 
1382        SOCK_FD_CLR(sock, &g_Sockets_Driver.m_fdsetWrite ); 
1383        SOCK_FD_CLR(sock, &g_Sockets_Driver.m_fdsetExcept); 
1384
1385        SOCK_FD_CLR(sock, &g_Sockets_Driver.m_nextReadSet );
1386        SOCK_FD_CLR(sock, &g_Sockets_Driver.m_nextWriteSet);
1387        SOCK_FD_CLR(sock, &g_Sockets_Driver.m_nextExcptSet);
1388    }
1389
1390    // notify select thread to include socket in select call
1391    HAL_SOCK_SignalSocketThread();
1392}
1393
1394//-----------------------------------------------------------------------------
1395//
1396//  RegisterSocket - socket tracking.  This method is used to track sockets
1397//    opened by this driver.  It does not include the fake socket.  Register
1398//    should be called after a socket is opened (via socket or accept methods).
1399//    The selectable parameter should only be true if the socket is in the 
1400//    listening or connected state
1401//
1402//-----------------------------------------------------------------------------
1403void Sockets_Driver::RegisterSocket( SOCK_SOCKET sock, BOOL selectable, BOOL fDebug )
1404{
1405    NATIVE_PROFILE_PAL_COM();
1406    if(sock == SOCK_SOCKET_ERROR)
1407    {
1408        ASSERT(FALSE);
1409        return;
1410    }
1411
1412    if(g_Sockets_Driver.m_cntSockets >= SOCKETS_MAX_COUNT) return;
1413
1414    GLOBAL_LOCK_SOCKETS(lock);
1415
1416    g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets].m_socket  = sock;
1417    g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets].m_flags   = 0;
1418    g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets].m_sslData = NULL;
1419
1420    if(selectable) SET_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets], SocketRegisterMap::c_SelectableSocket );
1421    if(fDebug    ) SET_SOCKET_FLAG(g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets], SocketRegisterMap::c_DebugSocket      );
1422
1423    g_Sockets_Driver.m_cntSockets++;
1424
1425    if(selectable)
1426    {
1427        SOCK_FD_SET(sock, &g_Sockets_Driver.m_nextReadSet );
1428        SOCK_FD_SET(sock, &g_Sockets_Driver.m_nextWriteSet);
1429        SOCK_FD_SET(sock, &g_Sockets_Driver.m_nextExcptSet);
1430        
1431        HAL_SOCK_SignalSocketThread();
1432    }
1433}
1434
1435//-----------------------------------------------------------------------------
1436//
1437//  UnregisterSocket - No longer track a given socket for clean up and selection.
1438//    This method should only be called immediately before closing down a socket.
1439//
1440//-----------------------------------------------------------------------------
1441void Sockets_Driver::UnregisterSocket( INT32 index )
1442{
1443    NATIVE_PROFILE_PAL_COM();
1444    GLOBAL_LOCK_SOCKETS(lock);
1445
1446    if(index < 0 || index >= g_Sockets_Driver.m_cntSockets) 
1447    {
1448        ASSERT(FALSE);
1449        return;
1450    }
1451
1452    SOCK_SOCKET sock = g_Sockets_Driver.m_socketHandles[index].m_socket;
1453
1454    SOCK_FD_CLR( sock, &g_Sockets_Driver.m_fdsetRead   ); 
1455    SOCK_FD_CLR( sock, &g_Sockets_Driver

Large files files are truncated, but you can click here to view the full file