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