PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/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
Possible License(s): Apache-2.0

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

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