| // Copyright 2017 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| #ifndef COBALT_WEBSOCKET_WEB_SOCKET_MESSAGE_CONTAINER_H_ |
| #define COBALT_WEBSOCKET_WEB_SOCKET_MESSAGE_CONTAINER_H_ |
| |
| #include <deque> |
| |
| #include "base/memory/ref_counted.h" |
| #include "cobalt/websocket/web_socket_frame_container.h" |
| #include "net/base/io_buffer.h" |
| #include "net/websockets/websocket_frame.h" |
| |
| namespace cobalt { |
| namespace websocket { |
| |
| const size_t kMaxMessagePayloadInBytes = 4 * 1024 * 1024; |
| COMPILE_ASSERT(kMaxMessagePayloadInBytes >= kMaxFramePayloadInBytes, |
| max_message_size_must_be_greater_than_max_payload_size); |
| |
| class WebSocketMessageContainer { |
| public: |
| typedef std::deque<WebSocketFrameContainer> WebSocketFrames; |
| |
| WebSocketMessageContainer() |
| : message_completed_(false), payload_size_bytes_(0) {} |
| ~WebSocketMessageContainer() { clear(); } |
| |
| void clear() { |
| message_completed_ = false; |
| payload_size_bytes_ = 0; |
| frames_.clear(); |
| } |
| |
| bool GetMessageOpCode(net::WebSocketFrameHeader::OpCode *op_code) const { |
| DCHECK(op_code); |
| if (empty()) { |
| return false; |
| } |
| |
| return frames_.begin()->GetFrameOpCode(op_code); |
| } |
| |
| bool IsMessageComplete() const { return message_completed_; } |
| |
| // Returns true if and only if it a text message. |
| // Note: It is valid to call this function on uncompleted messages. |
| bool IsTextMessage() const { |
| net::WebSocketFrameHeader::OpCode message_op_code = |
| net::WebSocketFrameHeader::kOpCodeContinuation; |
| |
| bool success = GetMessageOpCode(&message_op_code); |
| if (!success) { |
| DLOG(INFO) << "Unable to retrieve the message op code. Empty message?"; |
| return false; |
| } |
| |
| DCHECK_NE(message_op_code, net::WebSocketFrameHeader::kOpCodePing); |
| DCHECK_NE(message_op_code, net::WebSocketFrameHeader::kOpCodePong); |
| DCHECK_NE(message_op_code, net::WebSocketFrameHeader::kOpCodeClose); |
| |
| return (message_op_code == net::WebSocketFrameHeader::kOpCodeText); |
| } |
| |
| // Should only be called if IsMessageComplete() is false, and |
| // |frame_container| is a full frame. |
| bool Take(WebSocketFrameContainer *frame_container); |
| |
| std::size_t GetCurrentPayloadSizeBytes() const { return payload_size_bytes_; } |
| |
| scoped_refptr<net::IOBufferWithSize> GetMessageAsIOBuffer() const; |
| |
| const WebSocketFrames &GetFrames() const { return frames_; } |
| bool empty() const { return frames_.empty(); } |
| |
| private: |
| bool message_completed_; |
| std::size_t payload_size_bytes_; |
| WebSocketFrames frames_; |
| }; |
| |
| } // namespace websocket |
| } // namespace cobalt |
| |
| #endif // COBALT_WEBSOCKET_WEB_SOCKET_MESSAGE_CONTAINER_H_ |