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.

180 lines
6.9 KiB

4 months ago
  1. /*
  2. * IXWebSocket.h
  3. * Author: Benjamin Sergeant
  4. * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
  5. *
  6. * WebSocket RFC
  7. * https://tools.ietf.org/html/rfc6455
  8. */
  9. #pragma once
  10. #include "IXProgressCallback.h"
  11. #include "IXSocketTLSOptions.h"
  12. #include "IXWebSocketCloseConstants.h"
  13. #include "IXWebSocketErrorInfo.h"
  14. #include "IXWebSocketHttpHeaders.h"
  15. #include "IXWebSocketMessage.h"
  16. #include "IXWebSocketPerMessageDeflateOptions.h"
  17. #include "IXWebSocketSendInfo.h"
  18. #include "IXWebSocketSendData.h"
  19. #include "IXWebSocketTransport.h"
  20. #include <atomic>
  21. #include <condition_variable>
  22. #include <mutex>
  23. #include <string>
  24. #include <thread>
  25. namespace ix
  26. {
  27. // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants
  28. enum class ReadyState
  29. {
  30. Connecting = 0,
  31. Open = 1,
  32. Closing = 2,
  33. Closed = 3
  34. };
  35. using OnMessageCallback = std::function<void(const WebSocketMessagePtr&)>;
  36. using OnTrafficTrackerCallback = std::function<void(size_t size, bool incoming)>;
  37. class WebSocket
  38. {
  39. public:
  40. WebSocket();
  41. ~WebSocket();
  42. void setUrl(const std::string& url);
  43. // send extra headers in client handshake request
  44. void setExtraHeaders(const WebSocketHttpHeaders& headers);
  45. void setPerMessageDeflateOptions(
  46. const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
  47. void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
  48. void setPingInterval(int pingIntervalSecs);
  49. void enablePong();
  50. void disablePong();
  51. void enablePerMessageDeflate();
  52. void disablePerMessageDeflate();
  53. void addSubProtocol(const std::string& subProtocol);
  54. void setHandshakeTimeout(int handshakeTimeoutSecs);
  55. // Run asynchronously, by calling start and stop.
  56. void start();
  57. // stop is synchronous
  58. void stop(uint16_t code = WebSocketCloseConstants::kNormalClosureCode,
  59. const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
  60. // Run in blocking mode, by connecting first manually, and then calling run.
  61. WebSocketInitResult connect(int timeoutSecs);
  62. void run();
  63. // send is in text mode by default
  64. WebSocketSendInfo send(const std::string& data,
  65. bool binary = false,
  66. const OnProgressCallback& onProgressCallback = nullptr);
  67. WebSocketSendInfo sendBinary(const std::string& data,
  68. const OnProgressCallback& onProgressCallback = nullptr);
  69. WebSocketSendInfo sendBinary(const IXWebSocketSendData& data,
  70. const OnProgressCallback& onProgressCallback = nullptr);
  71. // does not check for valid UTF-8 characters. Caller must check that.
  72. WebSocketSendInfo sendUtf8Text(const std::string& text,
  73. const OnProgressCallback& onProgressCallback = nullptr);
  74. // does not check for valid UTF-8 characters. Caller must check that.
  75. WebSocketSendInfo sendUtf8Text(const IXWebSocketSendData& text,
  76. const OnProgressCallback& onProgressCallback = nullptr);
  77. WebSocketSendInfo sendText(const std::string& text,
  78. const OnProgressCallback& onProgressCallback = nullptr);
  79. WebSocketSendInfo ping(const std::string& text);
  80. void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode,
  81. const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
  82. void setOnMessageCallback(const OnMessageCallback& callback);
  83. bool isOnMessageCallbackRegistered() const;
  84. static void setTrafficTrackerCallback(const OnTrafficTrackerCallback& callback);
  85. static void resetTrafficTrackerCallback();
  86. ReadyState getReadyState() const;
  87. static std::string readyStateToString(ReadyState readyState);
  88. const std::string getUrl() const;
  89. const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const;
  90. int getPingInterval() const;
  91. size_t bufferedAmount() const;
  92. void enableAutomaticReconnection();
  93. void disableAutomaticReconnection();
  94. bool isAutomaticReconnectionEnabled() const;
  95. void setMaxWaitBetweenReconnectionRetries(uint32_t maxWaitBetweenReconnectionRetries);
  96. void setMinWaitBetweenReconnectionRetries(uint32_t minWaitBetweenReconnectionRetries);
  97. uint32_t getMaxWaitBetweenReconnectionRetries() const;
  98. uint32_t getMinWaitBetweenReconnectionRetries() const;
  99. const std::vector<std::string>& getSubProtocols();
  100. private:
  101. WebSocketSendInfo sendMessage(const IXWebSocketSendData& message,
  102. SendMessageKind sendMessageKind,
  103. const OnProgressCallback& callback = nullptr);
  104. bool isConnected() const;
  105. bool isClosing() const;
  106. void checkConnection(bool firstConnectionAttempt);
  107. static void invokeTrafficTrackerCallback(size_t size, bool incoming);
  108. // Server
  109. WebSocketInitResult connectToSocket(std::unique_ptr<Socket>,
  110. int timeoutSecs,
  111. bool enablePerMessageDeflate);
  112. WebSocketTransport _ws;
  113. std::string _url;
  114. WebSocketHttpHeaders _extraHeaders;
  115. WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
  116. SocketTLSOptions _socketTLSOptions;
  117. mutable std::mutex _configMutex; // protect all config variables access
  118. OnMessageCallback _onMessageCallback;
  119. static OnTrafficTrackerCallback _onTrafficTrackerCallback;
  120. std::atomic<bool> _stop;
  121. std::thread _thread;
  122. std::mutex _writeMutex;
  123. // Automatic reconnection
  124. std::atomic<bool> _automaticReconnection;
  125. static const uint32_t kDefaultMaxWaitBetweenReconnectionRetries;
  126. static const uint32_t kDefaultMinWaitBetweenReconnectionRetries;
  127. uint32_t _maxWaitBetweenReconnectionRetries;
  128. uint32_t _minWaitBetweenReconnectionRetries;
  129. // Make the sleeping in the automatic reconnection cancellable
  130. std::mutex _sleepMutex;
  131. std::condition_variable _sleepCondition;
  132. std::atomic<int> _handshakeTimeoutSecs;
  133. static const int kDefaultHandShakeTimeoutSecs;
  134. // enable or disable PONG frame response to received PING frame
  135. bool _enablePong;
  136. static const bool kDefaultEnablePong;
  137. // Optional ping and pong timeout
  138. int _pingIntervalSecs;
  139. int _pingTimeoutSecs;
  140. static const int kDefaultPingIntervalSecs;
  141. static const int kDefaultPingTimeoutSecs;
  142. // Subprotocols
  143. std::vector<std::string> _subProtocols;
  144. friend class WebSocketServer;
  145. };
  146. } // namespace ix