Introduction of IXWebSocketSendData (#347)
* Introduction of IXWebSocketSendData that makes it possible to not only send std::string but also std::vector<char/uint8_t> and char* without copying them to a std::string first. Add a sendUtf8Text() method that doesn't check for invalid UTF-8 characters. The caller must guarantee that the string only contains valid UTF-8 characters. * Updated usage.md: sendUtf8Text() and IXWebSocketSendData
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							2bc3afcf6c
						
					
				
				
					commit
					b5cf33a582
				
			| @@ -467,10 +467,28 @@ namespace ix | ||||
|         return (binary) ? sendBinary(data, onProgressCallback) : sendText(data, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocket::sendBinary(const std::string& text, | ||||
|     WebSocketSendInfo WebSocket::sendBinary(const std::string& data, | ||||
|                                             const OnProgressCallback& onProgressCallback) | ||||
|     { | ||||
|         return sendMessage(text, SendMessageKind::Binary, onProgressCallback); | ||||
|         return sendMessage(data, SendMessageKind::Binary, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocket::sendBinary(const IXWebSocketSendData& data, | ||||
|                                             const OnProgressCallback& onProgressCallback) | ||||
|     { | ||||
|         return sendMessage(data, SendMessageKind::Binary, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocket::sendUtf8Text(const std::string& text, | ||||
|                                               const OnProgressCallback& onProgressCallback) | ||||
|     { | ||||
|         return sendMessage(text, SendMessageKind::Text, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocket::sendUtf8Text(const IXWebSocketSendData& text, | ||||
|                                               const OnProgressCallback& onProgressCallback) | ||||
|     { | ||||
|         return sendMessage(text, SendMessageKind::Text, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocket::sendText(const std::string& text, | ||||
| @@ -494,7 +512,7 @@ namespace ix | ||||
|         return sendMessage(text, SendMessageKind::Ping); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocket::sendMessage(const std::string& text, | ||||
|     WebSocketSendInfo WebSocket::sendMessage(const IXWebSocketSendData& message, | ||||
|                                              SendMessageKind sendMessageKind, | ||||
|                                              const OnProgressCallback& onProgressCallback) | ||||
|     { | ||||
| @@ -516,19 +534,19 @@ namespace ix | ||||
|         { | ||||
|             case SendMessageKind::Text: | ||||
|             { | ||||
|                 webSocketSendInfo = _ws.sendText(text, onProgressCallback); | ||||
|                 webSocketSendInfo = _ws.sendText(message, onProgressCallback); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|             case SendMessageKind::Binary: | ||||
|             { | ||||
|                 webSocketSendInfo = _ws.sendBinary(text, onProgressCallback); | ||||
|                 webSocketSendInfo = _ws.sendBinary(message, onProgressCallback); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|             case SendMessageKind::Ping: | ||||
|             { | ||||
|                 webSocketSendInfo = _ws.sendPing(text); | ||||
|                 webSocketSendInfo = _ws.sendPing(message); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| #include "IXWebSocketMessage.h" | ||||
| #include "IXWebSocketPerMessageDeflateOptions.h" | ||||
| #include "IXWebSocketSendInfo.h" | ||||
| #include "IXWebSocketSendData.h" | ||||
| #include "IXWebSocketTransport.h" | ||||
| #include <atomic> | ||||
| #include <condition_variable> | ||||
| @@ -75,8 +76,16 @@ namespace ix | ||||
|         WebSocketSendInfo send(const std::string& data, | ||||
|                                bool binary = false, | ||||
|                                const OnProgressCallback& onProgressCallback = nullptr); | ||||
|         WebSocketSendInfo sendBinary(const std::string& text, | ||||
|         WebSocketSendInfo sendBinary(const std::string& data, | ||||
|                                      const OnProgressCallback& onProgressCallback = nullptr); | ||||
|         WebSocketSendInfo sendBinary(const IXWebSocketSendData& data, | ||||
|                                      const OnProgressCallback& onProgressCallback = nullptr); | ||||
|         // does not check for valid UTF-8 characters. Caller must check that. | ||||
|         WebSocketSendInfo sendUtf8Text(const std::string& text, | ||||
|                                        const OnProgressCallback& onProgressCallback = nullptr); | ||||
|         // does not check for valid UTF-8 characters. Caller must check that. | ||||
|         WebSocketSendInfo sendUtf8Text(const IXWebSocketSendData& text, | ||||
|                                        const OnProgressCallback& onProgressCallback = nullptr); | ||||
|         WebSocketSendInfo sendText(const std::string& text, | ||||
|                                    const OnProgressCallback& onProgressCallback = nullptr); | ||||
|         WebSocketSendInfo ping(const std::string& text); | ||||
| @@ -107,7 +116,7 @@ namespace ix | ||||
|         const std::vector<std::string>& getSubProtocols(); | ||||
|  | ||||
|     private: | ||||
|         WebSocketSendInfo sendMessage(const std::string& text, | ||||
|         WebSocketSendInfo sendMessage(const IXWebSocketSendData& message, | ||||
|                                       SendMessageKind sendMessageKind, | ||||
|                                       const OnProgressCallback& callback = nullptr); | ||||
|  | ||||
|   | ||||
| @@ -78,6 +78,11 @@ namespace ix | ||||
|                _decompressor->init(inflateBits, clientNoContextTakeover); | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflate::compress(const IXWebSocketSendData& in, std::string& out) | ||||
|     { | ||||
|         return _compressor->compress(in, out); | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflate::compress(const std::string& in, std::string& out) | ||||
|     { | ||||
|         return _compressor->compress(in, out); | ||||
|   | ||||
| @@ -36,6 +36,7 @@ | ||||
|  | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include "IXWebSocketSendData.h" | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -50,6 +51,7 @@ namespace ix | ||||
|         ~WebSocketPerMessageDeflate(); | ||||
|  | ||||
|         bool init(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); | ||||
|         bool compress(const IXWebSocketSendData& in, std::string& out); | ||||
|         bool compress(const std::string& in, std::string& out); | ||||
|         bool decompress(const std::string& in, std::string& out); | ||||
|  | ||||
|   | ||||
| @@ -78,6 +78,12 @@ namespace ix | ||||
|         return compressData(in, out); | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflateCompressor::compress(const IXWebSocketSendData& in, | ||||
|                                                         std::string& out) | ||||
|     { | ||||
|         return compressData(in, out); | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in, | ||||
|                                                         std::vector<uint8_t>& out) | ||||
|     { | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #include <array> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include "IXWebSocketSendData.h" | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -22,6 +23,7 @@ namespace ix | ||||
|         ~WebSocketPerMessageDeflateCompressor(); | ||||
|  | ||||
|         bool init(uint8_t deflateBits, bool clientNoContextTakeOver); | ||||
|         bool compress(const IXWebSocketSendData& in, std::string& out); | ||||
|         bool compress(const std::string& in, std::string& out); | ||||
|         bool compress(const std::string& in, std::vector<uint8_t>& out); | ||||
|         bool compress(const std::vector<uint8_t>& in, std::string& out); | ||||
|   | ||||
							
								
								
									
										128
									
								
								ixwebsocket/IXWebSocketSendData.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								ixwebsocket/IXWebSocketSendData.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| /* | ||||
|  *  IXWebSocketSendData.h | ||||
|  * | ||||
|  *  WebSocket (Binary/Text) send data buffer | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <iterator> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     /* | ||||
|     * IXWebSocketSendData implements a wrapper for std::string, std:vector<char/uint8_t> and char*. | ||||
|     * It removes the necessarity to copy the data or string into a std::string  | ||||
|     */ | ||||
|     class IXWebSocketSendData { | ||||
|     public: | ||||
|  | ||||
|         template<typename T> | ||||
|         struct IXWebSocketSendData_const_iterator | ||||
|             //: public std::iterator<std::forward_iterator_tag, T> | ||||
|         { | ||||
|             typedef IXWebSocketSendData_const_iterator<T> const_iterator; | ||||
|  | ||||
|             using iterator_category = std::forward_iterator_tag; | ||||
|             using difference_type = std::ptrdiff_t; | ||||
|             using value_type = T; | ||||
|             using pointer = value_type*; | ||||
|             using reference = const value_type&; | ||||
|  | ||||
|             pointer _ptr; | ||||
|         public: | ||||
|             IXWebSocketSendData_const_iterator() : _ptr(nullptr) {} | ||||
|             IXWebSocketSendData_const_iterator(pointer ptr) : _ptr(ptr) {} | ||||
|             ~IXWebSocketSendData_const_iterator() {} | ||||
|  | ||||
|             const_iterator  operator++(int) { return const_iterator(_ptr++); } | ||||
|             const_iterator& operator++() { ++_ptr; return *this; } | ||||
|             reference       operator* () const { return *_ptr; } | ||||
|             pointer         operator->() const { return _ptr; } | ||||
|             const_iterator  operator+ (const difference_type offset) const { return const_iterator(_ptr + offset); } | ||||
|             const_iterator  operator- (const difference_type offset) const { return const_iterator(_ptr - offset); } | ||||
|             difference_type operator- (const const_iterator& rhs) const { return _ptr - rhs._ptr; } | ||||
|             bool            operator==(const const_iterator& rhs) const { return _ptr == rhs._ptr; } | ||||
|             bool            operator!=(const const_iterator& rhs) const { return _ptr != rhs._ptr; } | ||||
|             const_iterator& operator+=(const difference_type offset) { _ptr += offset; return *this; } | ||||
|             const_iterator& operator-=(const difference_type offset) { _ptr -= offset; return *this; } | ||||
|         }; | ||||
|  | ||||
|         using const_iterator = IXWebSocketSendData_const_iterator<char>; | ||||
|  | ||||
|         /* The assigned std::string must be kept alive for the lifetime of the input buffer */ | ||||
|         IXWebSocketSendData(const std::string& str) | ||||
|             : _data(str.data()) | ||||
|             , _size(str.size()) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /* The assigned std::vector must be kept alive for the lifetime of the input buffer */ | ||||
|         IXWebSocketSendData(const std::vector<char>& v) | ||||
|             : _data(v.data()) | ||||
|             , _size(v.size()) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /* The assigned std::vector must be kept alive for the lifetime of the input buffer */ | ||||
|         IXWebSocketSendData(const std::vector<uint8_t>& v) | ||||
|             : _data(reinterpret_cast<const char*>(v.data())) | ||||
|             , _size(v.size()) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /* The assigned memory must be kept alive for the lifetime of the input buffer */ | ||||
|         IXWebSocketSendData(const char* data, size_t size) | ||||
|             : _data(data) | ||||
|             , _size(data == nullptr ? 0 : size) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         bool empty() const | ||||
|         { | ||||
|             return _data == nullptr || _size == 0; | ||||
|         } | ||||
|  | ||||
|         const char* c_str() const | ||||
|         { | ||||
|             return _data; | ||||
|         } | ||||
|  | ||||
|         const char* data() const | ||||
|         { | ||||
|             return _data; | ||||
|         } | ||||
|  | ||||
|         size_t size() const | ||||
|         { | ||||
|             return _size; | ||||
|         } | ||||
|  | ||||
|         inline const_iterator begin() const | ||||
|         { | ||||
|             return const_iterator(const_cast<char*>(_data)); | ||||
|         } | ||||
|  | ||||
|         inline const_iterator end() const | ||||
|         { | ||||
|             return const_iterator(const_cast<char*>(_data) + _size); | ||||
|         } | ||||
|  | ||||
|         inline const_iterator cbegin() const | ||||
|         { | ||||
|             return begin(); | ||||
|         } | ||||
|  | ||||
|         inline const_iterator cend() const | ||||
|         { | ||||
|             return end(); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         const char* _data; | ||||
|         const size_t _size; | ||||
|     }; | ||||
|  | ||||
| } | ||||
| @@ -776,9 +776,8 @@ namespace ix | ||||
|         return static_cast<unsigned>(seconds); | ||||
|     } | ||||
|  | ||||
|     template<class T> | ||||
|     WebSocketSendInfo WebSocketTransport::sendData(wsheader_type::opcode_type type, | ||||
|                                                    const T& message, | ||||
|                                                    const IXWebSocketSendData& message, | ||||
|                                                    bool compress, | ||||
|                                                    const OnProgressCallback& onProgressCallback) | ||||
|     { | ||||
| @@ -807,8 +806,9 @@ namespace ix | ||||
|             compressionError = false; | ||||
|             wireSize = _compressedMessage.size(); | ||||
|  | ||||
|             message_begin = _compressedMessage.cbegin(); | ||||
|             message_end = _compressedMessage.cend(); | ||||
|             IXWebSocketSendData compressedSendData(_compressedMessage); | ||||
|             message_begin = compressedSendData.cbegin(); | ||||
|             message_end = compressedSendData.cend(); | ||||
|         } | ||||
|  | ||||
|         { | ||||
| @@ -840,8 +840,8 @@ namespace ix | ||||
|             // | ||||
|             auto steps = wireSize / kChunkSize; | ||||
|  | ||||
|             std::string::const_iterator begin = message_begin; | ||||
|             std::string::const_iterator end = message_end; | ||||
|             auto begin = message_begin; | ||||
|             auto end = message_end; | ||||
|  | ||||
|             for (uint64_t i = 0; i < steps; ++i) | ||||
|             { | ||||
| @@ -980,7 +980,7 @@ namespace ix | ||||
|         return sendOnSocket(); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocketTransport::sendPing(const std::string& message) | ||||
|     WebSocketSendInfo WebSocketTransport::sendPing(const IXWebSocketSendData& message) | ||||
|     { | ||||
|         bool compress = false; | ||||
|         WebSocketSendInfo info = sendData(wsheader_type::PING, message, compress); | ||||
| @@ -994,7 +994,7 @@ namespace ix | ||||
|         return info; | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocketTransport::sendBinary(const std::string& message, | ||||
|     WebSocketSendInfo WebSocketTransport::sendBinary(const IXWebSocketSendData& message, | ||||
|                                                      const OnProgressCallback& onProgressCallback) | ||||
|  | ||||
|     { | ||||
| @@ -1002,7 +1002,7 @@ namespace ix | ||||
|             wsheader_type::BINARY_FRAME, message, _enablePerMessageDeflate, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocketTransport::sendText(const std::string& message, | ||||
|     WebSocketSendInfo WebSocketTransport::sendText(const IXWebSocketSendData& message, | ||||
|                                                    const OnProgressCallback& onProgressCallback) | ||||
|  | ||||
|     { | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "IXWebSocketPerMessageDeflate.h" | ||||
| #include "IXWebSocketPerMessageDeflateOptions.h" | ||||
| #include "IXWebSocketSendInfo.h" | ||||
| #include "IXWebSocketSendData.h" | ||||
| #include <atomic> | ||||
| #include <functional> | ||||
| #include <list> | ||||
| @@ -88,11 +89,11 @@ namespace ix | ||||
|                                             bool enablePerMessageDeflate); | ||||
|  | ||||
|         PollResult poll(); | ||||
|         WebSocketSendInfo sendBinary(const std::string& message, | ||||
|         WebSocketSendInfo sendBinary(const IXWebSocketSendData& message, | ||||
|                                      const OnProgressCallback& onProgressCallback); | ||||
|         WebSocketSendInfo sendText(const std::string& message, | ||||
|         WebSocketSendInfo sendText(const IXWebSocketSendData& message, | ||||
|                                    const OnProgressCallback& onProgressCallback); | ||||
|         WebSocketSendInfo sendPing(const std::string& message); | ||||
|         WebSocketSendInfo sendPing(const IXWebSocketSendData& message); | ||||
|  | ||||
|         void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, | ||||
|                    const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage, | ||||
| @@ -241,9 +242,8 @@ namespace ix | ||||
|         bool sendOnSocket(); | ||||
|         bool receiveFromSocket(); | ||||
|  | ||||
|         template<class T> | ||||
|         WebSocketSendInfo sendData(wsheader_type::opcode_type type, | ||||
|                                    const T& message, | ||||
|                                    const IXWebSocketSendData& message, | ||||
|                                    bool compress, | ||||
|                                    const OnProgressCallback& onProgressCallback = nullptr); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user