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.

130 lines
4.1 KiB

4 months ago
  1. /*
  2. * IXSocketServer.h
  3. * Author: Benjamin Sergeant
  4. * Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
  5. */
  6. #pragma once
  7. #include "IXConnectionState.h"
  8. #include "IXNetSystem.h"
  9. #include "IXSelectInterrupt.h"
  10. #include "IXSocketTLSOptions.h"
  11. #include <atomic>
  12. #include <condition_variable>
  13. #include <functional>
  14. #include <list>
  15. #include <memory>
  16. #include <mutex>
  17. #include <set>
  18. #include <string>
  19. #include <thread>
  20. #include <utility> // pair
  21. namespace ix
  22. {
  23. class Socket;
  24. class SocketServer
  25. {
  26. public:
  27. using ConnectionStateFactory = std::function<std::shared_ptr<ConnectionState>()>;
  28. // Each connection is handled by its own worker thread.
  29. // We use a list as we only care about remove and append operations.
  30. using ConnectionThreads =
  31. std::list<std::pair<std::shared_ptr<ConnectionState>, std::thread>>;
  32. SocketServer(int port = SocketServer::kDefaultPort,
  33. const std::string& host = SocketServer::kDefaultHost,
  34. int backlog = SocketServer::kDefaultTcpBacklog,
  35. size_t maxConnections = SocketServer::kDefaultMaxConnections,
  36. int addressFamily = SocketServer::kDefaultAddressFamily);
  37. virtual ~SocketServer();
  38. virtual void stop();
  39. // It is possible to override ConnectionState through inheritance
  40. // this method allows user to change the factory by returning an object
  41. // that inherits from ConnectionState but has its own methods.
  42. void setConnectionStateFactory(const ConnectionStateFactory& connectionStateFactory);
  43. const static int kDefaultPort;
  44. const static std::string kDefaultHost;
  45. const static int kDefaultTcpBacklog;
  46. const static size_t kDefaultMaxConnections;
  47. const static int kDefaultAddressFamily;
  48. void start();
  49. std::pair<bool, std::string> listen();
  50. void wait();
  51. void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
  52. int getPort();
  53. std::string getHost();
  54. int getBacklog();
  55. std::size_t getMaxConnections();
  56. int getAddressFamily();
  57. protected:
  58. // Logging
  59. void logError(const std::string& str);
  60. void logInfo(const std::string& str);
  61. void stopAcceptingConnections();
  62. private:
  63. // Member variables
  64. int _port;
  65. std::string _host;
  66. int _backlog;
  67. size_t _maxConnections;
  68. int _addressFamily;
  69. // socket for accepting connections
  70. socket_t _serverFd;
  71. std::atomic<bool> _stop;
  72. std::mutex _logMutex;
  73. // background thread to wait for incoming connections
  74. std::thread _thread;
  75. void run();
  76. void onSetTerminatedCallback();
  77. // background thread to cleanup (join) terminated threads
  78. std::atomic<bool> _stopGc;
  79. std::thread _gcThread;
  80. void runGC();
  81. // the list of (connectionState, threads) for each connections
  82. ConnectionThreads _connectionsThreads;
  83. std::mutex _connectionsThreadsMutex;
  84. // used to have the main control thread for a server
  85. // wait for a 'terminate' notification without busy polling
  86. std::condition_variable _conditionVariable;
  87. std::mutex _conditionVariableMutex;
  88. // the factory to create ConnectionState objects
  89. ConnectionStateFactory _connectionStateFactory;
  90. virtual void handleConnection(std::unique_ptr<Socket>,
  91. std::shared_ptr<ConnectionState> connectionState) = 0;
  92. virtual size_t getConnectedClientsCount() = 0;
  93. // Returns true if all connection threads are joined
  94. void closeTerminatedThreads();
  95. size_t getConnectionsThreadsCount();
  96. SocketTLSOptions _socketTLSOptions;
  97. // to wake up from select
  98. SelectInterruptPtr _acceptSelectInterrupt;
  99. // used by the gc thread, to know that a thread needs to be garbage collected
  100. // as a connection
  101. std::condition_variable _conditionVariableGC;
  102. std::mutex _conditionVariableMutexGC;
  103. };
  104. } // namespace ix