[email protected] | 256d273 | 2012-04-24 23:26:37 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 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 REMOTING_PROTOCOL_BUFFERED_SOCKET_WRITER_H_ | ||||
6 | #define REMOTING_PROTOCOL_BUFFERED_SOCKET_WRITER_H_ | ||||
7 | |||||
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame] | 8 | #include <list> |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 9 | |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 10 | #include "base/callback.h" |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame] | 11 | #include "base/synchronization/lock.h" |
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 12 | #include "base/threading/non_thread_safe.h" |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 13 | #include "net/base/io_buffer.h" |
14 | #include "net/socket/socket.h" | ||||
15 | |||||
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 16 | namespace net { |
17 | class Socket; | ||||
18 | } // namespace net | ||||
19 | |||||
20 | namespace remoting { | ||||
[email protected] | d87c404 | 2010-11-04 00:46:01 | [diff] [blame] | 21 | namespace protocol { |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 22 | |
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 23 | // BufferedSocketWriter and BufferedDatagramWriter implement write data queue |
24 | // for stream and datagram sockets. BufferedSocketWriterBase is a base class | ||||
25 | // that implements base functionality common for streams and datagrams. | ||||
26 | // These classes are particularly useful when data comes from a thread | ||||
27 | // that doesn't own the socket, as Write() can be called from any thread. | ||||
28 | // Whenever new data is written it is just put in the queue, and then written | ||||
29 | // on the thread that owns the socket. GetBufferChunks() and GetBufferSize() | ||||
30 | // can be used to throttle writes. | ||||
31 | |||||
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 32 | class BufferedSocketWriterBase : public base::NonThreadSafe { |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 33 | public: |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 34 | typedef base::Callback<void(int)> WriteFailedCallback; |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 35 | |
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 36 | BufferedSocketWriterBase(); |
37 | virtual ~BufferedSocketWriterBase(); | ||||
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 38 | |
39 | // Initializes the writer. Must be called on the thread that will be used | ||||
40 | // to access the socket in the future. |callback| will be called after each | ||||
[email protected] | 182ec8f2 | 2011-08-11 02:14:35 | [diff] [blame] | 41 | // failed write. Caller retains ownership of |socket|. |
42 | // TODO(sergeyu): Change it so that it take ownership of |socket|. | ||||
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 43 | void Init(net::Socket* socket, const WriteFailedCallback& callback); |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 44 | |
45 | // Puts a new data chunk in the buffer. Returns false and doesn't enqueue | ||||
46 | // the data if called before Init(). Can be called on any thread. | ||||
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 47 | bool Write(scoped_refptr<net::IOBufferWithSize> buffer, |
48 | const base::Closure& done_task); | ||||
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 49 | |
50 | // Returns current size of the buffer. Can be called on any thread. | ||||
51 | int GetBufferSize(); | ||||
52 | |||||
53 | // Returns number of chunks that are currently in the buffer waiting | ||||
54 | // to be written. Can be called on any thread. | ||||
55 | int GetBufferChunks(); | ||||
56 | |||||
[email protected] | 86dbc72 | 2011-06-30 23:23:30 | [diff] [blame] | 57 | // Stops writing and drops current buffers. Must be called on the |
58 | // network thread. | ||||
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 59 | void Close(); |
60 | |||||
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 61 | protected: |
[email protected] | 27626e6 | 2012-08-01 01:48:02 | [diff] [blame] | 62 | struct PendingPacket; |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame] | 63 | typedef std::list<PendingPacket*> DataQueue; |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 64 | |
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 65 | DataQueue queue_; |
66 | int buffer_size_; | ||||
67 | |||||
[email protected] | 27626e6 | 2012-08-01 01:48:02 | [diff] [blame] | 68 | // Removes element from the front of the queue and returns |done_task| for |
69 | // that element. Called from AdvanceBufferPosition() implementation, which | ||||
70 | // then returns result of this function to its caller. | ||||
71 | base::Closure PopQueue(); | ||||
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame] | 72 | |
[email protected] | e221eeb | 2010-11-11 21:52:57 | [diff] [blame] | 73 | // Following three methods must be implemented in child classes. |
[email protected] | 27626e6 | 2012-08-01 01:48:02 | [diff] [blame] | 74 | |
75 | // Returns next packet that needs to be written to the socket. Implementation | ||||
76 | // must set |*buffer| to NULL if there is nothing left in the queue. | ||||
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 77 | virtual void GetNextPacket(net::IOBuffer** buffer, int* size) = 0; |
[email protected] | 27626e6 | 2012-08-01 01:48:02 | [diff] [blame] | 78 | |
79 | // Returns closure that must be executed or null closure if the last write | ||||
80 | // didn't complete any messages. | ||||
81 | virtual base::Closure AdvanceBufferPosition(int written) = 0; | ||||
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 82 | |
[email protected] | e221eeb | 2010-11-11 21:52:57 | [diff] [blame] | 83 | // This method is called whenever there is an error writing to the socket. |
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 84 | virtual void OnError(int result) = 0; |
[email protected] | e221eeb | 2010-11-11 21:52:57 | [diff] [blame] | 85 | |
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 86 | private: |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 87 | void DoWrite(); |
[email protected] | 27626e6 | 2012-08-01 01:48:02 | [diff] [blame] | 88 | void HandleWriteResult(int result, bool* write_again); |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 89 | void OnWritten(int result); |
90 | |||||
[email protected] | e221eeb | 2010-11-11 21:52:57 | [diff] [blame] | 91 | // This method is called when an error is encountered. |
92 | void HandleError(int result); | ||||
93 | |||||
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 94 | net::Socket* socket_; |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 95 | WriteFailedCallback write_failed_callback_; |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 96 | |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 97 | bool write_pending_; |
98 | |||||
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 99 | bool closed_; |
[email protected] | 27626e6 | 2012-08-01 01:48:02 | [diff] [blame] | 100 | |
101 | bool* destroyed_flag_; | ||||
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 102 | }; |
103 | |||||
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 104 | class BufferedSocketWriter : public BufferedSocketWriterBase { |
105 | public: | ||||
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 106 | BufferedSocketWriter(); |
dcheng | 562aba5 | 2014-10-21 12:30:14 | [diff] [blame] | 107 | ~BufferedSocketWriter() override; |
[email protected] | 256d273 | 2012-04-24 23:26:37 | [diff] [blame] | 108 | |
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 109 | protected: |
dcheng | 562aba5 | 2014-10-21 12:30:14 | [diff] [blame] | 110 | void GetNextPacket(net::IOBuffer** buffer, int* size) override; |
111 | base::Closure AdvanceBufferPosition(int written) override; | ||||
112 | void OnError(int result) override; | ||||
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 113 | |
114 | private: | ||||
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 115 | scoped_refptr<net::DrainableIOBuffer> current_buf_; |
116 | }; | ||||
117 | |||||
118 | class BufferedDatagramWriter : public BufferedSocketWriterBase { | ||||
119 | public: | ||||
[email protected] | a3464dca | 2012-05-24 01:27:09 | [diff] [blame] | 120 | BufferedDatagramWriter(); |
dcheng | 562aba5 | 2014-10-21 12:30:14 | [diff] [blame] | 121 | ~BufferedDatagramWriter() override; |
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 122 | |
123 | protected: | ||||
dcheng | 562aba5 | 2014-10-21 12:30:14 | [diff] [blame] | 124 | void GetNextPacket(net::IOBuffer** buffer, int* size) override; |
125 | base::Closure AdvanceBufferPosition(int written) override; | ||||
126 | void OnError(int result) override; | ||||
[email protected] | aacbaac | 2010-10-20 23:53:49 | [diff] [blame] | 127 | }; |
128 | |||||
[email protected] | d87c404 | 2010-11-04 00:46:01 | [diff] [blame] | 129 | } // namespace protocol |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 130 | } // namespace remoting |
131 | |||||
132 | #endif // REMOTING_PROTOCOL_BUFFERED_SOCKET_WRITER_H_ |