OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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/tcp_server_socket_libevent.h" | |
6 | |
7 #include <errno.h> | |
8 #include <fcntl.h> | |
9 #include <netdb.h> | |
10 #include <sys/socket.h> | |
11 | |
12 #include "base/eintr_wrapper.h" | |
13 #include "net/base/ip_endpoint.h" | |
14 #include "net/base/net_errors.h" | |
15 #include "net/base/net_util.h" | |
16 #if defined(OS_POSIX) | |
17 #include <netinet/in.h> | |
18 #endif | |
19 #if defined(USE_SYSTEM_LIBEVENT) | |
20 #include <event.h> | |
21 #else | |
22 #include "third_party/libevent/event.h" | |
23 #endif | |
24 | |
25 namespace net { | |
26 | |
27 namespace { | |
28 | |
29 const int kInvalidSocket = -1; | |
30 | |
31 } // namespace | |
32 | |
33 TCPServerSocketLibevent::TCPServerSocketLibevent( | |
34 net::NetLog* net_log, | |
35 const net::NetLog::Source& source) | |
36 : socket_(kInvalidSocket), | |
37 accept_socket_(NULL), | |
38 accept_address_(NULL), | |
39 accept_callback_(NULL), | |
40 net_log_(net_log), | |
41 net_log_source_(source) { | |
willchan no longer on Chromium
2011/04/13 16:08:51
You should probably be creating new NetLog events
Sergey Ulanov
2011/04/13 21:20:19
Done.
| |
42 } | |
43 | |
44 TCPServerSocketLibevent::~TCPServerSocketLibevent() { | |
45 if (socket_ != kInvalidSocket) | |
46 Close(); | |
47 } | |
48 | |
49 int TCPServerSocketLibevent::Listen(const IPEndPoint& address, int backlog) { | |
50 DCHECK(CalledOnValidThread()); | |
51 DCHECK_GT(backlog, 0); | |
52 DCHECK_EQ(socket_, kInvalidSocket); | |
53 | |
54 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
55 if (socket_ < 0) { | |
56 PLOG(ERROR) << "socket() returned an error"; | |
57 return MapSystemError(errno); | |
58 } | |
59 | |
60 if (SetNonBlocking(socket_)) { | |
61 int result = MapSystemError(errno); | |
62 Close(); | |
63 return result; | |
64 } | |
65 | |
66 struct sockaddr_storage addr_storage; | |
67 size_t addr_len = sizeof(addr_storage); | |
68 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
69 if (!address.ToSockAddr(addr, &addr_len)) | |
70 return ERR_INVALID_ARGUMENT; | |
71 | |
72 int result = bind(socket_, addr, addr_len); | |
73 if (result < 0) { | |
74 PLOG(ERROR) << "bind() returned an error"; | |
75 result = MapSystemError(errno); | |
76 Close(); | |
77 return result; | |
78 } | |
79 | |
80 result = listen(socket_, backlog); | |
81 if (result < 0) { | |
82 PLOG(ERROR) << "listen() returned an error"; | |
83 result = MapSystemError(errno); | |
84 Close(); | |
85 return result; | |
86 } | |
87 | |
88 return OK; | |
89 } | |
90 | |
91 int TCPServerSocketLibevent::GetLocalAddress(IPEndPoint* address) const { | |
92 DCHECK(CalledOnValidThread()); | |
93 DCHECK(address); | |
94 | |
95 struct sockaddr_storage addr_storage; | |
96 socklen_t addr_len = sizeof(addr_storage); | |
97 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
98 if (getsockname(socket_, addr, &addr_len) < 0) | |
99 return MapSystemError(errno); | |
100 if (!address->FromSockAddr(addr, addr_len)) | |
101 return ERR_FAILED; | |
102 | |
103 return OK; | |
104 } | |
105 | |
106 int TCPServerSocketLibevent::Accept( | |
107 TCPClientSocket** socket, net::IPEndPoint* address, | |
108 CompletionCallback* callback) { | |
109 DCHECK(CalledOnValidThread()); | |
110 DCHECK(socket); | |
111 DCHECK(address); | |
112 DCHECK(callback); | |
113 DCHECK(!accept_callback_); | |
114 | |
115 int result = AcceptInternal(socket, address); | |
116 | |
117 if (result == ERR_IO_PENDING) { | |
118 if (!MessageLoopForIO::current()->WatchFileDescriptor( | |
119 socket_, true, MessageLoopForIO::WATCH_READ, | |
120 &accept_socket_watcher_, this)) { | |
121 PLOG(ERROR) << "WatchFileDescriptor failed on read"; | |
122 return MapSystemError(errno); | |
123 } | |
124 | |
125 accept_socket_ = socket; | |
126 accept_address_ = address; | |
127 accept_callback_ = callback; | |
128 } | |
129 | |
130 return result; | |
131 } | |
132 | |
133 int TCPServerSocketLibevent::AcceptInternal( | |
134 TCPClientSocket** socket, net::IPEndPoint* address) { | |
135 struct sockaddr_storage addr_storage; | |
136 socklen_t addr_len = sizeof(addr_storage); | |
137 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
138 | |
139 int result = HANDLE_EINTR(accept(socket_, addr, &addr_len)); | |
140 if (result < 0) | |
141 return MapSystemError(errno); | |
142 | |
143 if (!address->FromSockAddr(addr, addr_len)) { | |
144 NOTREACHED(); | |
145 HANDLE_EINTR(close(result)); | |
146 return ERR_FAILED; | |
147 } | |
148 *socket = new TCPClientSocket(AddressList(), net_log_, net_log_source_); | |
willchan no longer on Chromium
2011/04/13 16:08:51
You should probably be constructing a AddressList
Sergey Ulanov
2011/04/13 21:20:19
Done.
| |
149 (*socket)->AdoptSocket(result); | |
150 return OK; | |
151 } | |
152 | |
153 void TCPServerSocketLibevent::Close() { | |
154 if (socket_ != kInvalidSocket) { | |
155 HANDLE_EINTR(close(socket_)); | |
156 socket_ = kInvalidSocket; | |
157 } | |
158 } | |
159 | |
160 void TCPServerSocketLibevent::OnFileCanReadWithoutBlocking(int fd) { | |
161 DCHECK(CalledOnValidThread()); | |
162 | |
163 int result = AcceptInternal(accept_socket_, accept_address_); | |
164 if (result == 0) { | |
willchan no longer on Chromium
2011/04/13 16:08:51
result == OK
Sergey Ulanov
2011/04/13 21:20:19
Actually this code was incorrect: Callback should
| |
165 CompletionCallback* c = accept_callback_; | |
166 accept_callback_ = NULL; | |
167 accept_socket_ = NULL; | |
168 accept_address_ = NULL; | |
169 c->Run(0); | |
willchan no longer on Chromium
2011/04/13 16:08:51
Run(OK)
Sergey Ulanov
2011/04/13 21:20:19
Done.
| |
170 } else { | |
171 PLOG(ERROR) << "accept() returned error after read event was signalled"; | |
172 } | |
173 } | |
174 | |
175 void TCPServerSocketLibevent::OnFileCanWriteWithoutBlocking(int fd) { | |
176 NOTREACHED(); | |
177 } | |
178 | |
179 } // namespace net | |
OLD | NEW |