1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROMECAST_NET_SMALL_MESSAGE_SOCKET_H_ 6 #define CHROMECAST_NET_SMALL_MESSAGE_SOCKET_H_ 7 8 #include <memory> 9 10 #include "base/macros.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/memory/weak_ptr.h" 13 14 namespace base { 15 class SequencedTaskRunner; 16 } // namespace base 17 18 namespace net { 19 class GrowableIOBuffer; 20 class IOBuffer; 21 class Socket; 22 } // namespace net 23 24 namespace chromecast { 25 class IOBufferPool; 26 27 // Sends small messages (< 64 KB) over a Socket. All methods must be called on 28 // the same sequence. Any of the virtual methods can destroy this object if 29 // desired. 30 class SmallMessageSocket { 31 public: 32 class Delegate { 33 public: 34 // Called when sending becomes possible again, if a previous attempt to send 35 // was rejected. OnSendUnblocked()36 virtual void OnSendUnblocked() {} 37 38 // Called when an unrecoverable error occurs while sending or receiving. Is 39 // only called asynchronously. OnError(int error)40 virtual void OnError(int error) {} 41 42 // Called when the end of stream has been read. No more data will be 43 // received. OnEndOfStream()44 virtual void OnEndOfStream() {} 45 46 // Called when a message has been received and there is no buffer pool. The 47 // |data| buffer contains |size| bytes of data. Return |true| to continue 48 // reading messages after OnMessage() returns. 49 virtual bool OnMessage(char* data, size_t size) = 0; 50 51 // Called when a message has been received. The |buffer| contains |size| 52 // bytes of data, which includes the first 2 bytes which are the size in 53 // network byte order. Note that these 2 bytes are not included in 54 // OnMessage()! Return |true| to continue receiving messages. 55 virtual bool OnMessageBuffer(scoped_refptr<net::IOBuffer> buffer, 56 size_t size); 57 58 protected: 59 virtual ~Delegate() = default; 60 }; 61 62 SmallMessageSocket(Delegate* delegate, std::unique_ptr<net::Socket> socket); 63 virtual ~SmallMessageSocket(); 64 socket()65 net::Socket* socket() const { return socket_.get(); } task_runner()66 base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } buffer_pool()67 IOBufferPool* buffer_pool() const { return buffer_pool_.get(); } 68 69 // Adds a |buffer_pool| used to allocate buffers to receive messages into; 70 // received messages are passed to OnMessageBuffer(). If a message would be 71 // too big to fit in a pool-provided buffer, a dynamically allocated IOBuffer 72 // will be used instead for that message. 73 void UseBufferPool(scoped_refptr<IOBufferPool> buffer_pool); 74 75 // Removes the buffer pool; subsequent received messages will be passed to 76 // OnMessage(). 77 void RemoveBufferPool(); 78 79 // Prepares a buffer to send a message of the given |message_size|. Returns 80 // nullptr if sending is not allowed right now (ie, another send is currently 81 // in progress). Otherwise, returns a buffer at least large enough to contain 82 // |message_size| bytes. The caller should fill in the buffer as desired and 83 // then call Send() to send the finished message. 84 // If nullptr is returned, then OnSendUnblocked() will be called once sending 85 // is possible again. 86 void* PrepareSend(size_t message_size); 87 void Send(); 88 89 // Sends an already-prepared buffer of data, if possible. The first 2 bytes of 90 // the buffer must contain the size of the rest of the data, encoded as a 91 // 16-bit integer in big-endian byte order. Returns true if the buffer will be 92 // sent; returns false if sending is not allowed right now (ie, another send 93 // is currently in progress). If false is returned, then OnSendUnblocked() 94 // will be called once sending is possible again. 95 bool SendBuffer(scoped_refptr<net::IOBuffer> data, size_t size); 96 97 // Enables receiving messages from the stream. Messages will be received and 98 // passed to OnMessage() until either an error occurs, the end of stream is 99 // reached, or OnMessage() returns false. If OnMessage() returns false, you 100 // may call ReceiveMessages() to start receiving again. OnMessage() will not 101 // be called synchronously from within this method (it always posts a task). 102 void ReceiveMessages(); 103 104 // Same as ReceiveMessages(), but OnMessage() may be called synchronously. 105 // This is more efficient because it doesn't post a task to ensure 106 // asynchronous reads. 107 void ReceiveMessagesSynchronously(); 108 109 private: 110 class BufferWrapper; 111 112 void OnWriteComplete(int result); 113 bool HandleWriteResult(int result); 114 void OnError(int error); 115 116 void Read(); 117 void OnReadComplete(int result); 118 bool HandleReadResult(int result); 119 bool HandleCompletedMessages(); 120 bool HandleCompletedMessageBuffers(); 121 void ActivateBufferPool(char* current_data, size_t current_size); 122 123 Delegate* const delegate_; 124 const std::unique_ptr<net::Socket> socket_; 125 const scoped_refptr<base::SequencedTaskRunner> task_runner_; 126 127 const scoped_refptr<net::GrowableIOBuffer> write_storage_; 128 const scoped_refptr<BufferWrapper> write_buffer_; 129 bool send_blocked_ = false; 130 131 const scoped_refptr<net::GrowableIOBuffer> read_storage_; 132 133 scoped_refptr<IOBufferPool> buffer_pool_; 134 const scoped_refptr<BufferWrapper> read_buffer_; 135 136 bool in_message_ = false; 137 138 base::WeakPtrFactory<SmallMessageSocket> weak_factory_; 139 140 DISALLOW_COPY_AND_ASSIGN(SmallMessageSocket); 141 }; 142 143 } // namespace chromecast 144 145 #endif // CHROMECAST_NET_SMALL_MESSAGE_SOCKET_H_ 146