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