OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 REMOTING_PROTOCOL_BUFFERED_SOCKET_WRITER_H_ | |
6 #define REMOTING_PROTOCOL_BUFFERED_SOCKET_WRITER_H_ | |
7 | |
8 #include <list> | |
9 | |
10 #include "base/callback.h" | |
11 #include "base/synchronization/lock.h" | |
12 #include "base/threading/non_thread_safe.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "net/socket/socket.h" | |
15 | |
16 namespace net { | |
17 class Socket; | |
18 } // namespace net | |
19 | |
20 namespace remoting { | |
21 namespace protocol { | |
22 | |
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 | |
32 class BufferedSocketWriterBase : public base::NonThreadSafe { | |
33 public: | |
34 typedef base::Callback<void(int)> WriteFailedCallback; | |
35 | |
36 BufferedSocketWriterBase(); | |
37 virtual ~BufferedSocketWriterBase(); | |
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 | |
41 // failed write. Caller retains ownership of |socket|. | |
42 // TODO(sergeyu): Change it so that it take ownership of |socket|. | |
43 void Init(net::Socket* socket, const WriteFailedCallback& callback); | |
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. | |
47 bool Write(scoped_refptr<net::IOBufferWithSize> buffer, | |
48 const base::Closure& done_task); | |
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 | |
57 // Stops writing and drops current buffers. Must be called on the | |
58 // network thread. | |
59 void Close(); | |
60 | |
61 protected: | |
62 struct PendingPacket; | |
63 typedef std::list<PendingPacket*> DataQueue; | |
64 | |
65 DataQueue queue_; | |
66 int buffer_size_; | |
67 | |
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(); | |
72 | |
73 // Following three methods must be implemented in child classes. | |
74 | |
75 // Returns next packet that needs to be written to the socket. Implementation | |
76 // must set |*buffer| to nullptr if there is nothing left in the queue. | |
77 virtual void GetNextPacket(net::IOBuffer** buffer, int* size) = 0; | |
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; | |
82 | |
83 // This method is called whenever there is an error writing to the socket. | |
84 virtual void OnError(int result) = 0; | |
85 | |
86 private: | |
87 void DoWrite(); | |
88 void HandleWriteResult(int result, bool* write_again); | |
89 void OnWritten(int result); | |
90 | |
91 // This method is called when an error is encountered. | |
92 void HandleError(int result); | |
93 | |
94 net::Socket* socket_; | |
95 WriteFailedCallback write_failed_callback_; | |
96 | |
97 bool write_pending_; | |
98 | |
99 bool closed_; | |
100 | |
101 bool* destroyed_flag_; | |
102 }; | |
103 | |
104 class BufferedSocketWriter : public BufferedSocketWriterBase { | |
105 public: | |
106 BufferedSocketWriter(); | |
107 ~BufferedSocketWriter() override; | |
108 | |
109 protected: | |
110 void GetNextPacket(net::IOBuffer** buffer, int* size) override; | |
111 base::Closure AdvanceBufferPosition(int written) override; | |
112 void OnError(int result) override; | |
113 | |
114 private: | |
115 scoped_refptr<net::DrainableIOBuffer> current_buf_; | |
116 }; | |
117 | |
118 class BufferedDatagramWriter : public BufferedSocketWriterBase { | |
119 public: | |
120 BufferedDatagramWriter(); | |
121 ~BufferedDatagramWriter() override; | |
122 | |
123 protected: | |
124 void GetNextPacket(net::IOBuffer** buffer, int* size) override; | |
125 base::Closure AdvanceBufferPosition(int written) override; | |
126 void OnError(int result) override; | |
127 }; | |
128 | |
129 } // namespace protocol | |
130 } // namespace remoting | |
131 | |
132 #endif // REMOTING_PROTOCOL_BUFFERED_SOCKET_WRITER_H_ | |
OLD | NEW |