Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Side by Side Diff: net/socket/stream_listen_socket.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/socket/stream_listen_socket.h ('k') | net/socket/stream_socket.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #include "net/socket/stream_listen_socket.h"
6
7 #if defined(OS_WIN)
8 // winsock2.h must be included first in order to ensure it is included before
9 // windows.h.
10 #include <winsock2.h>
11 #elif defined(OS_POSIX)
12 #include <arpa/inet.h>
13 #include <errno.h>
14 #include <netinet/in.h>
15 #include <sys/socket.h>
16 #include <sys/types.h>
17 #include "net/base/net_errors.h"
18 #endif
19
20 #include "base/logging.h"
21 #include "base/memory/ref_counted.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/posix/eintr_wrapper.h"
24 #include "base/profiler/scoped_tracker.h"
25 #include "base/sys_byteorder.h"
26 #include "base/threading/platform_thread.h"
27 #include "build/build_config.h"
28 #include "net/base/ip_endpoint.h"
29 #include "net/base/net_errors.h"
30 #include "net/base/net_util.h"
31 #include "net/socket/socket_descriptor.h"
32
33 using std::string;
34
35 #if defined(OS_WIN)
36 typedef int socklen_t;
37 #endif // defined(OS_WIN)
38
39 namespace net {
40
41 namespace {
42
43 const int kReadBufSize = 4096;
44
45 } // namespace
46
47 #if defined(OS_WIN)
48 const int StreamListenSocket::kSocketError = SOCKET_ERROR;
49 #elif defined(OS_POSIX)
50 const int StreamListenSocket::kSocketError = -1;
51 #endif
52
53 StreamListenSocket::StreamListenSocket(SocketDescriptor s,
54 StreamListenSocket::Delegate* del)
55 : socket_delegate_(del),
56 socket_(s),
57 reads_paused_(false),
58 has_pending_reads_(false) {
59 #if defined(OS_WIN)
60 socket_event_ = WSACreateEvent();
61 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT.
62 WatchSocket(NOT_WAITING);
63 #elif defined(OS_POSIX)
64 wait_state_ = NOT_WAITING;
65 #endif
66 }
67
68 StreamListenSocket::~StreamListenSocket() {
69 CloseSocket();
70 #if defined(OS_WIN)
71 if (socket_event_) {
72 WSACloseEvent(socket_event_);
73 socket_event_ = WSA_INVALID_EVENT;
74 }
75 #endif
76 }
77
78 void StreamListenSocket::Send(const char* bytes, int len,
79 bool append_linefeed) {
80 SendInternal(bytes, len);
81 if (append_linefeed)
82 SendInternal("\r\n", 2);
83 }
84
85 void StreamListenSocket::Send(const string& str, bool append_linefeed) {
86 Send(str.data(), static_cast<int>(str.length()), append_linefeed);
87 }
88
89 int StreamListenSocket::GetLocalAddress(IPEndPoint* address) {
90 SockaddrStorage storage;
91 if (getsockname(socket_, storage.addr, &storage.addr_len)) {
92 #if defined(OS_WIN)
93 int err = WSAGetLastError();
94 #else
95 int err = errno;
96 #endif
97 return MapSystemError(err);
98 }
99 if (!address->FromSockAddr(storage.addr, storage.addr_len))
100 return ERR_ADDRESS_INVALID;
101 return OK;
102 }
103
104 int StreamListenSocket::GetPeerAddress(IPEndPoint* address) {
105 SockaddrStorage storage;
106 if (getpeername(socket_, storage.addr, &storage.addr_len)) {
107 #if defined(OS_WIN)
108 int err = WSAGetLastError();
109 #else
110 int err = errno;
111 #endif
112 return MapSystemError(err);
113 }
114
115 if (!address->FromSockAddr(storage.addr, storage.addr_len))
116 return ERR_ADDRESS_INVALID;
117
118 return OK;
119 }
120
121 SocketDescriptor StreamListenSocket::AcceptSocket() {
122 SocketDescriptor conn = HANDLE_EINTR(accept(socket_, NULL, NULL));
123 if (conn == kInvalidSocket)
124 LOG(ERROR) << "Error accepting connection.";
125 else
126 SetNonBlocking(conn);
127 return conn;
128 }
129
130 void StreamListenSocket::SendInternal(const char* bytes, int len) {
131 char* send_buf = const_cast<char *>(bytes);
132 int len_left = len;
133 while (true) {
134 int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0));
135 if (sent == len_left) { // A shortcut to avoid extraneous checks.
136 break;
137 }
138 if (sent == kSocketError) {
139 #if defined(OS_WIN)
140 if (WSAGetLastError() != WSAEWOULDBLOCK) {
141 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
142 #elif defined(OS_POSIX)
143 if (errno != EWOULDBLOCK && errno != EAGAIN) {
144 LOG(ERROR) << "send failed: errno==" << errno;
145 #endif
146 break;
147 }
148 // Otherwise we would block, and now we have to wait for a retry.
149 // Fall through to PlatformThread::YieldCurrentThread()
150 } else {
151 // sent != len_left according to the shortcut above.
152 // Shift the buffer start and send the remainder after a short while.
153 send_buf += sent;
154 len_left -= sent;
155 }
156 base::PlatformThread::YieldCurrentThread();
157 }
158 }
159
160 void StreamListenSocket::Listen() {
161 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog?
162 if (listen(socket_, backlog) == -1) {
163 // TODO(erikkay): error handling.
164 LOG(ERROR) << "Could not listen on socket.";
165 return;
166 }
167 #if defined(OS_POSIX)
168 WatchSocket(WAITING_ACCEPT);
169 #endif
170 }
171
172 void StreamListenSocket::Read() {
173 char buf[kReadBufSize + 1]; // +1 for null termination.
174 int len;
175 do {
176 len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0));
177 if (len == kSocketError) {
178 #if defined(OS_WIN)
179 int err = WSAGetLastError();
180 if (err == WSAEWOULDBLOCK) {
181 #elif defined(OS_POSIX)
182 if (errno == EWOULDBLOCK || errno == EAGAIN) {
183 #endif
184 break;
185 } else {
186 // TODO(ibrar): some error handling required here.
187 break;
188 }
189 } else if (len == 0) {
190 // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need
191 // to call it here.
192 #if defined(OS_POSIX)
193 Close();
194 #endif
195 } else {
196 // TODO(ibrar): maybe change DidRead to take a length instead.
197 DCHECK_GT(len, 0);
198 DCHECK_LE(len, kReadBufSize);
199 buf[len] = 0; // Already create a buffer with +1 length.
200 socket_delegate_->DidRead(this, buf, len);
201 }
202 } while (len == kReadBufSize);
203 }
204
205 void StreamListenSocket::Close() {
206 #if defined(OS_POSIX)
207 if (wait_state_ == NOT_WAITING)
208 return;
209 wait_state_ = NOT_WAITING;
210 #endif
211 UnwatchSocket();
212 socket_delegate_->DidClose(this);
213 }
214
215 void StreamListenSocket::CloseSocket() {
216 if (socket_ != kInvalidSocket) {
217 UnwatchSocket();
218 #if defined(OS_WIN)
219 closesocket(socket_);
220 #elif defined(OS_POSIX)
221 close(socket_);
222 #endif
223 }
224 }
225
226 void StreamListenSocket::WatchSocket(WaitState state) {
227 #if defined(OS_WIN)
228 WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ);
229 watcher_.StartWatching(socket_event_, this);
230 #elif defined(OS_POSIX)
231 // Implicitly calls StartWatchingFileDescriptor().
232 base::MessageLoopForIO::current()->WatchFileDescriptor(
233 socket_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this);
234 wait_state_ = state;
235 #endif
236 }
237
238 void StreamListenSocket::UnwatchSocket() {
239 #if defined(OS_WIN)
240 watcher_.StopWatching();
241 #elif defined(OS_POSIX)
242 watcher_.StopWatchingFileDescriptor();
243 #endif
244 }
245
246 // TODO(ibrar): We can add these functions into OS dependent files.
247 #if defined(OS_WIN)
248 // MessageLoop watcher callback.
249 void StreamListenSocket::OnObjectSignaled(HANDLE object) {
250 // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
251 tracked_objects::ScopedTracker tracking_profile(
252 FROM_HERE_WITH_EXPLICIT_FUNCTION(
253 "418183 StreamListenSocket::OnObjectSignaled"));
254
255 WSANETWORKEVENTS ev;
256 if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) {
257 // TODO
258 return;
259 }
260
261 // If both FD_CLOSE and FD_READ are set we only call Read().
262 // This will cause OnObjectSignaled to be called immediately again
263 // unless this socket is destroyed in Read().
264 if ((ev.lNetworkEvents & (FD_CLOSE | FD_READ)) == FD_CLOSE) {
265 Close();
266 // Close might have deleted this object. We should return immediately.
267 return;
268 }
269 // The object was reset by WSAEnumNetworkEvents. Watch for the next signal.
270 watcher_.StartWatching(object, this);
271
272 if (ev.lNetworkEvents == 0) {
273 // Occasionally the event is set even though there is no new data.
274 // The net seems to think that this is ignorable.
275 return;
276 }
277 if (ev.lNetworkEvents & FD_ACCEPT) {
278 Accept();
279 }
280 if (ev.lNetworkEvents & FD_READ) {
281 if (reads_paused_) {
282 has_pending_reads_ = true;
283 } else {
284 Read();
285 // Read might have deleted this object. We should return immediately.
286 }
287 }
288 }
289 #elif defined(OS_POSIX)
290 void StreamListenSocket::OnFileCanReadWithoutBlocking(int fd) {
291 switch (wait_state_) {
292 case WAITING_ACCEPT:
293 Accept();
294 break;
295 case WAITING_READ:
296 if (reads_paused_) {
297 has_pending_reads_ = true;
298 } else {
299 Read();
300 }
301 break;
302 default:
303 // Close() is called by Read() in the Linux case.
304 NOTREACHED();
305 break;
306 }
307 }
308
309 void StreamListenSocket::OnFileCanWriteWithoutBlocking(int fd) {
310 // MessagePumpLibevent callback, we don't listen for write events
311 // so we shouldn't ever reach here.
312 NOTREACHED();
313 }
314
315 #endif
316
317 void StreamListenSocket::PauseReads() {
318 DCHECK(!reads_paused_);
319 reads_paused_ = true;
320 }
321
322 void StreamListenSocket::ResumeReads() {
323 DCHECK(reads_paused_);
324 reads_paused_ = false;
325 if (has_pending_reads_) {
326 has_pending_reads_ = false;
327 Read();
328 }
329 }
330
331 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/stream_listen_socket.h ('k') | net/socket/stream_socket.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698