/DeviceCode/pal/COM/sockets/sockets.cpp
C++ | 1485 lines | 1022 code | 295 blank | 168 comment | 177 complexity | 2b98d70dc4199a57c38dbad01030b274 MD5 | raw file
Possible License(s): Apache-2.0
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, ¤t); 672 673 info.ipaddr = current.ipaddr; 674 info.macAddressLen = current.macAddressLen; 675 memcpy( &info.macAddressBuffer[0], ¤t.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.m_fdsetWrite ); 1456 SOCK_FD_CLR( sock, &g_Sockets_Driver.m_fdsetExcept ); 1457 1458 SOCK_FD_CLR( sock, &g_Sockets_Driver.m_nextReadSet ); 1459 SOCK_FD_CLR( sock, &g_Sockets_Driver.m_nextWriteSet ); 1460 SOCK_FD_CLR( sock, &g_Sockets_Driver.m_nextExcptSet ); 1461 1462 g_Sockets_Driver.m_cntSockets--; 1463 1464 if(index != g_Sockets_Driver.m_cntSockets) 1465 { 1466 memcpy( &g_Sockets_Driver.m_socketHandles[index], &g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets], sizeof(g_Sockets_Driver.m_socketHandles[index]) ); 1467 } 1468 1469 g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets].m_socket = SOCK_SOCKET_ERROR; 1470 g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets].m_flags = 0; 1471 g_Sockets_Driver.m_socketHandles[g_Sockets_Driver.m_cntSockets].m_socket = 0; 1472} 1473 1474#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED) 1475#pragma arm section zidata = "g_SOCKETS_Driver" 1476#endif 1477 1478BOOL Sockets_Driver::s_initialized=FALSE; 1479BOOL Sockets_Driver::s_wirelessInitialized=FALSE; 1480BOOL Sockets_Driver::s_discoveryInitialized=FALSE; 1481 1482#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED) 1483#pragma arm section zidata 1484#endif 1485