You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IConnectionServer.cpp 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include "IConnection.h"
  2. #include "IConnectionServer.h"
  3. #include "IConnection.inl"
  4. #include <cstring>
  5. #include <iostream>
  6. #if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
  7. #include <netinet/in.h>
  8. #include <netinet/tcp.h>
  9. #include <netdb.h>
  10. #include <cerrno>
  11. #elif defined TARGET_OS_Windows
  12. #else
  13. #endif
  14. namespace Socket {
  15. class CConnectionServer final : public TConnection<IConnectionServer>
  16. {
  17. public:
  18. bool listen(const size_t port) override
  19. {
  20. if (!open()) { return false; }
  21. int reuseAddress = 1;
  22. #if defined TARGET_OS_Windows
  23. setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&reuseAddress), sizeof(reuseAddress));
  24. #else
  25. ::setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddress, sizeof(reuseAddress));
  26. #endif
  27. struct sockaddr_in localHostAddress;
  28. memset(&localHostAddress, 0, sizeof(localHostAddress));
  29. localHostAddress.sin_family = AF_INET;
  30. localHostAddress.sin_port = htons(static_cast<unsigned short>(port));
  31. localHostAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  32. if (bind(m_socket, reinterpret_cast<struct sockaddr*>(&localHostAddress), sizeof(localHostAddress)) == -1)
  33. {
  34. /*
  35. switch(errno)
  36. {
  37. case EBADF: std::cout << "EBADF" << std::endl; break;
  38. case ENOTSOCK: std::cout << "ENOTSOCK" << std::endl; break;
  39. case EADDRINUSE: std::cout << "EADDRINUSE" << std::endl; break;
  40. case EINVAL: std::cout << "EINVAL" << std::endl; break;
  41. case EROFS: std::cout << "EROFS" << std::endl; break;
  42. case EFAULT: std::cout << "EFAULT" << std::endl; break;
  43. case ENAMETOOLONG: std::cout << "ENAMETOOLONG" << std::endl; break;
  44. case ENOENT: std::cout << "ENOENT" << std::endl; break;
  45. case ENOMEM: std::cout << "ENOMEM" << std::endl; break;
  46. case ENOTDIR: std::cout << "ENOTDIR" << std::endl; break;
  47. case EACCES: std::cout << "EACCES" << std::endl; break;
  48. case ELOOP: std::cout << "ELOOP" << std::endl; break;
  49. default: std::cout << "Bind_unknown" << std::endl;
  50. }
  51. */
  52. return false;
  53. }
  54. if (::listen(m_socket, 32) == -1)
  55. {
  56. /*
  57. switch(errno)
  58. {
  59. case EADDRINUSE: std::cout << "EADDRINUSE" << std::endl; break;
  60. case EBADF: std::cout << "EBADF" << std::endl; break;
  61. case ENOTSOCK: std::cout << "ENOTSOCK" << std::endl; break;
  62. case EOPNOTSUPP: std::cout << "EOPNOTSUPP" << std::endl; break;
  63. default: std::cout << "Listen_unknown" << std::endl;
  64. }
  65. */
  66. return false;
  67. }
  68. return true;
  69. }
  70. IConnection* accept() override
  71. {
  72. struct sockaddr_in clientAddress;
  73. #if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
  74. socklen_t clientAddressSize = sizeof(clientAddress);
  75. #elif defined TARGET_OS_Windows
  76. int clientAddressSize = sizeof(clientAddress);
  77. #else
  78. #endif
  79. const int clientSocket = int(::accept(m_socket, reinterpret_cast<struct sockaddr*>(&clientAddress), &clientAddressSize));
  80. if (clientSocket == -1) { return nullptr; }
  81. return new TConnection<IConnection>(int(clientSocket));
  82. }
  83. bool getSocketPort(size_t& port) override
  84. {
  85. struct sockaddr_in socketInfo;
  86. #if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
  87. socklen_t socketInfoLength = sizeof(socketInfo);
  88. #elif defined TARGET_OS_Windows
  89. int socketInfoLength = sizeof(socketInfo);
  90. #endif
  91. if (getsockname(m_socket, reinterpret_cast<sockaddr*>(&socketInfo), &socketInfoLength) == -1) { return false; }
  92. port = size_t(ntohs(socketInfo.sin_port));
  93. return true;
  94. }
  95. };
  96. IConnectionServer* createConnectionServer() { return new CConnectionServer(); }
  97. } // namespace Socket