select-cli.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * Implementation of do_select() for network.c to use, suitable for use
  3. * when there's no GUI window to have network activity reported to.
  4. *
  5. * It uses WSAEventSelect, where available, to convert network
  6. * activity into activity on an event object, for integration into an
  7. * event loop that includes WaitForMultipleObjects.
  8. *
  9. * It also maintains a list of currently active sockets, which can be
  10. * retrieved by a front end that wants to use WinSock's synchronous
  11. * select() function.
  12. */
  13. #include "putty.h"
  14. static tree234 *winselcli_sockets;
  15. static int socket_cmp(void *av, void *bv)
  16. {
  17. return memcmp(av, bv, sizeof(SOCKET));
  18. }
  19. HANDLE winselcli_event = INVALID_HANDLE_VALUE;
  20. void winselcli_setup(void)
  21. {
  22. if (!winselcli_sockets)
  23. winselcli_sockets = newtree234(socket_cmp);
  24. if (p_WSAEventSelect && winselcli_event == INVALID_HANDLE_VALUE)
  25. winselcli_event = CreateEvent(NULL, false, false, NULL);
  26. }
  27. SOCKET winselcli_unique_socket(void)
  28. {
  29. if (!winselcli_sockets)
  30. return INVALID_SOCKET;
  31. assert(count234(winselcli_sockets) <= 1);
  32. SOCKET *p = index234(winselcli_sockets, 0);
  33. if (!p)
  34. return INVALID_SOCKET;
  35. return *p;
  36. }
  37. const char *do_select(SOCKET skt, bool enable)
  38. {
  39. /* Check everything's been set up, for convenience of callers. */
  40. winselcli_setup();
  41. if (enable) {
  42. SOCKET *ptr = snew(SOCKET);
  43. *ptr = skt;
  44. if (add234(winselcli_sockets, ptr) != ptr)
  45. sfree(ptr); /* already there */
  46. } else {
  47. SOCKET *ptr = del234(winselcli_sockets, &skt);
  48. if (ptr)
  49. sfree(ptr);
  50. }
  51. if (p_WSAEventSelect) {
  52. int events;
  53. if (enable) {
  54. events = (FD_CONNECT | FD_READ | FD_WRITE |
  55. FD_OOB | FD_CLOSE | FD_ACCEPT);
  56. } else {
  57. events = 0;
  58. }
  59. if (p_WSAEventSelect(skt, winselcli_event, events) == SOCKET_ERROR)
  60. return winsock_error_string(p_WSAGetLastError());
  61. }
  62. return NULL;
  63. }