Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "build/build_config.h" | 5 #include "net/base/stream_listen_socket.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 // winsock2.h must be included first in order to ensure it is included before | 8 // winsock2.h must be included first in order to ensure it is included before |
| 9 // windows.h. | 9 // windows.h. |
| 10 #include <winsock2.h> | 10 #include <winsock2.h> |
| 11 #elif defined(OS_POSIX) | 11 #elif defined(OS_POSIX) |
| 12 #include <errno.h> | 12 #include <errno.h> |
| 13 #include <sys/types.h> | 13 #include <sys/types.h> |
| 14 #include <sys/socket.h> | 14 #include <sys/socket.h> |
| 15 #include <netinet/in.h> | 15 #include <netinet/in.h> |
| 16 #include <arpa/inet.h> | 16 #include <arpa/inet.h> |
| 17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 #endif | 18 #endif |
| 19 | 19 |
| 20 #include "build/build_config.h" | |
| 20 #include "base/eintr_wrapper.h" | 21 #include "base/eintr_wrapper.h" |
| 21 #include "base/sys_byteorder.h" | 22 #include "base/sys_byteorder.h" |
| 22 #include "base/threading/platform_thread.h" | 23 #include "base/threading/platform_thread.h" |
| 23 #include "net/base/net_util.h" | 24 #include "net/base/net_util.h" |
| 24 #include "net/base/tcp_listen_socket.h" | 25 |
| 26 using std::string; | |
| 25 | 27 |
| 26 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
| 27 typedef int socklen_t; | 29 typedef int socklen_t; |
| 28 #endif // defined(OS_WIN) | 30 #endif // defined(OS_WIN) |
| 29 | 31 |
| 30 namespace net { | 32 namespace net { |
| 31 | 33 |
| 32 namespace { | 34 namespace { |
| 33 | 35 |
| 34 const int kReadBufSize = 4096; | 36 const int kReadBufSize = 4096; |
| 35 | 37 |
| 36 } // namespace | 38 } // namespace |
| 37 | 39 |
| 38 #if defined(OS_WIN) | 40 #if defined(OS_WIN) |
| 39 const SOCKET TCPListenSocket::kInvalidSocket = INVALID_SOCKET; | 41 const SOCKET StreamListenSocket::kInvalidSocket = INVALID_SOCKET; |
| 40 const int TCPListenSocket::kSocketError = SOCKET_ERROR; | 42 const int StreamListenSocket::kSocketError = SOCKET_ERROR; |
| 41 #elif defined(OS_POSIX) | 43 #elif defined(OS_POSIX) |
| 42 const SOCKET TCPListenSocket::kInvalidSocket = -1; | 44 const SOCKET StreamListenSocket::kInvalidSocket = -1; |
| 43 const int TCPListenSocket::kSocketError = -1; | 45 const int StreamListenSocket::kSocketError = -1; |
| 44 #endif | 46 #endif |
| 45 | 47 |
| 46 TCPListenSocket* TCPListenSocket::CreateAndListen( | 48 StreamListenSocket::StreamListenSocket(SOCKET s, |
| 47 const std::string& ip, int port, ListenSocket::ListenSocketDelegate *del) { | 49 StreamListenSocket::Delegate* del) |
| 48 SOCKET s = CreateAndBind(ip, port); | 50 : socket_delegate_(del), |
| 49 if (s == kInvalidSocket) { | |
| 50 // TODO(erikkay): error handling | |
| 51 } else { | |
| 52 TCPListenSocket* sock = new TCPListenSocket(s, del); | |
| 53 sock->Listen(); | |
| 54 return sock; | |
| 55 } | |
| 56 return NULL; | |
| 57 } | |
| 58 | |
| 59 void TCPListenSocket::PauseReads() { | |
| 60 DCHECK(!reads_paused_); | |
| 61 reads_paused_ = true; | |
| 62 } | |
| 63 | |
| 64 void TCPListenSocket::ResumeReads() { | |
| 65 DCHECK(reads_paused_); | |
| 66 reads_paused_ = false; | |
| 67 if (has_pending_reads_) { | |
| 68 has_pending_reads_ = false; | |
| 69 Read(); | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 TCPListenSocket::TCPListenSocket(SOCKET s, | |
| 74 ListenSocket::ListenSocketDelegate *del) | |
| 75 : ListenSocket(del), | |
| 76 socket_(s), | 51 socket_(s), |
| 77 reads_paused_(false), | 52 reads_paused_(false), |
| 78 has_pending_reads_(false) { | 53 has_pending_reads_(false) { |
| 79 #if defined(OS_WIN) | 54 #if defined(OS_WIN) |
| 80 socket_event_ = WSACreateEvent(); | 55 socket_event_ = WSACreateEvent(); |
| 81 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT | 56 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT. |
| 82 WatchSocket(NOT_WAITING); | 57 WatchSocket(NOT_WAITING); |
| 83 #elif defined(OS_POSIX) | 58 #elif defined(OS_POSIX) |
| 84 wait_state_ = NOT_WAITING; | 59 wait_state_ = NOT_WAITING; |
| 85 #endif | 60 #endif |
| 86 } | 61 } |
| 87 | 62 |
| 88 TCPListenSocket::~TCPListenSocket() { | 63 StreamListenSocket::~StreamListenSocket() { |
| 89 #if defined(OS_WIN) | 64 #if defined(OS_WIN) |
| 90 if (socket_event_) { | 65 if (socket_event_) { |
| 91 WSACloseEvent(socket_event_); | 66 WSACloseEvent(socket_event_); |
| 92 socket_event_ = WSA_INVALID_EVENT; | 67 socket_event_ = WSA_INVALID_EVENT; |
| 93 } | 68 } |
| 94 #endif | 69 #endif |
| 95 CloseSocket(socket_); | 70 CloseSocket(socket_); |
| 96 } | 71 } |
| 97 | 72 |
| 98 SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) { | 73 void StreamListenSocket::Send(const char* bytes, int len, |
| 99 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | 74 bool append_linefeed) { |
| 100 if (s != kInvalidSocket) { | 75 SendInternal(bytes, len); |
| 101 #if defined(OS_POSIX) | 76 if (append_linefeed) |
| 102 // Allow rapid reuse. | 77 SendInternal("\r\n", 2); |
| 103 static const int kOn = 1; | |
| 104 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); | |
| 105 #endif | |
| 106 sockaddr_in addr; | |
| 107 memset(&addr, 0, sizeof(addr)); | |
| 108 addr.sin_family = AF_INET; | |
| 109 addr.sin_addr.s_addr = inet_addr(ip.c_str()); | |
| 110 addr.sin_port = base::HostToNet16(port); | |
| 111 if (bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) { | |
| 112 #if defined(OS_WIN) | |
| 113 closesocket(s); | |
| 114 #elif defined(OS_POSIX) | |
| 115 close(s); | |
| 116 #endif | |
| 117 s = kInvalidSocket; | |
| 118 } | |
| 119 } | |
| 120 return s; | |
| 121 } | 78 } |
| 122 | 79 |
| 123 SOCKET TCPListenSocket::Accept(SOCKET s) { | 80 void StreamListenSocket::Send(const string& str, bool append_linefeed) { |
| 124 sockaddr_in from; | 81 Send(str.data(), static_cast<int>(str.length()), append_linefeed); |
| 125 socklen_t from_len = sizeof(from); | 82 } |
| 126 SOCKET conn = | 83 |
| 127 HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len)); | 84 SOCKET StreamListenSocket::AcceptSocket() { |
| 128 if (conn != kInvalidSocket) { | 85 SOCKET conn = HANDLE_EINTR(accept(socket_, NULL, NULL)); |
| 86 if (conn == kInvalidSocket) | |
| 87 LOG(ERROR) << "Error accepting connection."; | |
| 88 else | |
| 129 SetNonBlocking(conn); | 89 SetNonBlocking(conn); |
| 130 } | |
| 131 return conn; | 90 return conn; |
| 132 } | 91 } |
| 133 | 92 |
| 134 void TCPListenSocket::SendInternal(const char* bytes, int len) { | 93 void StreamListenSocket::SendInternal(const char* bytes, int len) { |
| 135 char* send_buf = const_cast<char *>(bytes); | 94 char* send_buf = const_cast<char*>(bytes); |
| 136 int len_left = len; | 95 int len_left = len; |
| 137 while (true) { | 96 while (true) { |
| 138 int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0)); | 97 int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0)); |
| 139 if (sent == len_left) { // A shortcut to avoid extraneous checks. | 98 if (sent == len_left) { // A shortcut to avoid extraneous checks. |
| 140 break; | 99 break; |
| 141 } | 100 } |
| 142 if (sent == kSocketError) { | 101 if (sent == kSocketError) { |
| 143 #if defined(OS_WIN) | 102 #if defined(OS_WIN) |
| 144 if (WSAGetLastError() != WSAEWOULDBLOCK) { | 103 if (WSAGetLastError() != WSAEWOULDBLOCK) { |
| 145 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); | 104 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); |
| 146 #elif defined(OS_POSIX) | 105 #elif defined(OS_POSIX) |
| 147 if (errno != EWOULDBLOCK && errno != EAGAIN) { | 106 if (errno != EWOULDBLOCK && errno != EAGAIN) { |
| 148 LOG(ERROR) << "send failed: errno==" << errno; | 107 LOG(ERROR) << "send failed: errno==" << errno; |
| 149 #endif | 108 #endif |
| 150 break; | 109 break; |
| 151 } | 110 } |
| 152 // Otherwise we would block, and now we have to wait for a retry. | 111 // Otherwise we would block, and now we have to wait for a retry. |
| 153 // Fall through to PlatformThread::YieldCurrentThread() | 112 // Fall through to PlatformThread::YieldCurrentThread(). |
| 113 } else if (sent == 0) { | |
| 114 // Socket was disconnected. | |
| 115 Close(); | |
| 154 } else { | 116 } else { |
| 155 // sent != len_left according to the shortcut above. | 117 // sent != len_left according to the shortcut above. |
| 156 // Shift the buffer start and send the remainder after a short while. | 118 // Shift the buffer start and send the remainder after a short while. |
| 157 send_buf += sent; | 119 send_buf += sent; |
| 158 len_left -= sent; | 120 len_left -= sent; |
| 159 } | 121 } |
| 160 base::PlatformThread::YieldCurrentThread(); | 122 base::PlatformThread::YieldCurrentThread(); |
| 161 } | 123 } |
| 162 } | 124 } |
| 163 | 125 |
| 164 void TCPListenSocket::Listen() { | 126 void StreamListenSocket::Listen() { |
| 165 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? | 127 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? |
| 166 listen(socket_, backlog); | 128 if (listen(socket_, backlog) == -1) { |
|
mmenke
2012/04/30 19:11:44
nit: Suggest you keep the error handling TODO her
Philippe
2012/05/03 14:27:52
Done.
| |
| 167 // TODO(erikkay): error handling | 129 LOG(ERROR) << "Could not listen on socket."; |
| 130 return; | |
| 131 } | |
| 168 #if defined(OS_POSIX) | 132 #if defined(OS_POSIX) |
| 169 WatchSocket(WAITING_ACCEPT); | 133 WatchSocket(WAITING_ACCEPT); |
| 170 #endif | 134 #endif |
| 171 } | 135 } |
| 172 | 136 |
| 173 void TCPListenSocket::Accept() { | 137 void StreamListenSocket::Read() { |
| 174 SOCKET conn = Accept(socket_); | 138 char buf[kReadBufSize + 1]; // +1 for null termination. |
| 175 if (conn != kInvalidSocket) { | |
| 176 scoped_refptr<TCPListenSocket> sock( | |
| 177 new TCPListenSocket(conn, socket_delegate_)); | |
| 178 // it's up to the delegate to AddRef if it wants to keep it around | |
| 179 #if defined(OS_POSIX) | |
| 180 sock->WatchSocket(WAITING_READ); | |
| 181 #endif | |
| 182 socket_delegate_->DidAccept(this, sock); | |
| 183 } else { | |
| 184 // TODO(ibrar): some error handling required here | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 void TCPListenSocket::Read() { | |
| 189 char buf[kReadBufSize + 1]; // +1 for null termination | |
| 190 int len; | 139 int len; |
| 191 do { | 140 do { |
| 192 len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0)); | 141 len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0)); |
| 193 if (len == kSocketError) { | 142 if (len == kSocketError) { |
| 194 #if defined(OS_WIN) | 143 #if defined(OS_WIN) |
| 195 int err = WSAGetLastError(); | 144 int err = WSAGetLastError(); |
| 196 if (err == WSAEWOULDBLOCK) { | 145 if (err == WSAEWOULDBLOCK) { |
| 197 #elif defined(OS_POSIX) | 146 #elif defined(OS_POSIX) |
| 198 if (errno == EWOULDBLOCK || errno == EAGAIN) { | 147 if (errno == EWOULDBLOCK || errno == EAGAIN) { |
| 199 #endif | 148 #endif |
| 200 break; | 149 break; |
| 201 } else { | 150 } else { |
| 202 // TODO(ibrar): some error handling required here | 151 // TODO(ibrar): some error handling required here. |
| 203 break; | 152 break; |
| 204 } | 153 } |
| 205 } else if (len == 0) { | 154 } else if (len == 0) { |
| 206 // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need | 155 // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need |
| 207 // to call it here. | 156 // to call it here. |
| 208 #if defined(OS_POSIX) | 157 #if defined(OS_POSIX) |
| 209 Close(); | 158 Close(); |
| 210 #endif | 159 #endif |
| 211 } else { | 160 } else { |
| 212 // TODO(ibrar): maybe change DidRead to take a length instead | 161 // TODO(ibrar): maybe change DidRead to take a length instead. |
| 213 DCHECK_GT(len, 0); | 162 DCHECK_GT(len, 0); |
| 214 DCHECK_LE(len, kReadBufSize); | 163 DCHECK_LE(len, kReadBufSize); |
| 215 buf[len] = 0; // already create a buffer with +1 length | 164 buf[len] = 0; // Already create a buffer with +1 length. |
| 216 socket_delegate_->DidRead(this, buf, len); | 165 socket_delegate_->DidRead(this, buf, len); |
| 217 } | 166 } |
| 218 } while (len == kReadBufSize); | 167 } while (len == kReadBufSize); |
| 219 } | 168 } |
| 220 | 169 |
| 221 void TCPListenSocket::Close() { | 170 void StreamListenSocket::Close() { |
| 222 #if defined(OS_POSIX) | 171 #if defined(OS_POSIX) |
| 223 if (wait_state_ == NOT_WAITING) | 172 if (wait_state_ == NOT_WAITING) |
| 224 return; | 173 return; |
| 225 wait_state_ = NOT_WAITING; | 174 wait_state_ = NOT_WAITING; |
| 226 #endif | 175 #endif |
| 227 UnwatchSocket(); | 176 UnwatchSocket(); |
| 228 socket_delegate_->DidClose(this); | 177 socket_delegate_->DidClose(this); |
| 229 } | 178 } |
| 230 | 179 |
| 231 void TCPListenSocket::CloseSocket(SOCKET s) { | 180 void StreamListenSocket::CloseSocket(SOCKET s) { |
| 232 if (s && s != kInvalidSocket) { | 181 if (s && s != kInvalidSocket) { |
| 233 UnwatchSocket(); | 182 UnwatchSocket(); |
| 234 #if defined(OS_WIN) | 183 #if defined(OS_WIN) |
| 235 closesocket(s); | 184 closesocket(s); |
| 236 #elif defined(OS_POSIX) | 185 #elif defined(OS_POSIX) |
| 237 close(s); | 186 close(s); |
| 238 #endif | 187 #endif |
| 239 } | 188 } |
| 240 } | 189 } |
| 241 | 190 |
| 242 void TCPListenSocket::WatchSocket(WaitState state) { | 191 void StreamListenSocket::WatchSocket(WaitState state) { |
| 243 #if defined(OS_WIN) | 192 #if defined(OS_WIN) |
| 244 WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ); | 193 WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ); |
| 245 watcher_.StartWatching(socket_event_, this); | 194 watcher_.StartWatching(socket_event_, this); |
| 246 #elif defined(OS_POSIX) | 195 #elif defined(OS_POSIX) |
| 247 // Implicitly calls StartWatchingFileDescriptor(). | 196 // Implicitly calls StartWatchingFileDescriptor(). |
| 248 MessageLoopForIO::current()->WatchFileDescriptor( | 197 MessageLoopForIO::current()->WatchFileDescriptor( |
| 249 socket_, true, MessageLoopForIO::WATCH_READ, &watcher_, this); | 198 socket_, true, MessageLoopForIO::WATCH_READ, &watcher_, this); |
| 250 wait_state_ = state; | 199 wait_state_ = state; |
| 251 #endif | 200 #endif |
| 252 } | 201 } |
| 253 | 202 |
| 254 void TCPListenSocket::UnwatchSocket() { | 203 void StreamListenSocket::UnwatchSocket() { |
| 255 #if defined(OS_WIN) | 204 #if defined(OS_WIN) |
| 256 watcher_.StopWatching(); | 205 watcher_.StopWatching(); |
| 257 #elif defined(OS_POSIX) | 206 #elif defined(OS_POSIX) |
| 258 watcher_.StopWatchingFileDescriptor(); | 207 watcher_.StopWatchingFileDescriptor(); |
| 259 #endif | 208 #endif |
| 260 } | 209 } |
| 261 | 210 |
| 262 // TODO(ibrar): We can add these functions into OS dependent files | 211 // TODO(ibrar): We can add these functions into OS dependent files. |
| 263 #if defined(OS_WIN) | 212 #if defined(OS_WIN) |
| 264 // MessageLoop watcher callback | 213 // MessageLoop watcher callback. |
| 265 void TCPListenSocket::OnObjectSignaled(HANDLE object) { | 214 void StreamListenSocket::OnObjectSignaled(HANDLE object) { |
| 266 WSANETWORKEVENTS ev; | 215 WSANETWORKEVENTS ev; |
| 267 if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) { | 216 if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) { |
| 268 // TODO | 217 // TODO |
| 269 return; | 218 return; |
| 270 } | 219 } |
| 271 | 220 |
| 272 // The object was reset by WSAEnumNetworkEvents. Watch for the next signal. | 221 // The object was reset by WSAEnumNetworkEvents. Watch for the next signal. |
| 273 watcher_.StartWatching(object, this); | 222 watcher_.StartWatching(object, this); |
| 274 | 223 |
| 275 if (ev.lNetworkEvents == 0) { | 224 if (ev.lNetworkEvents == 0) { |
| 276 // Occasionally the event is set even though there is no new data. | 225 // Occasionally the event is set even though there is no new data. |
| 277 // The net seems to think that this is ignorable. | 226 // The net seems to think that this is ignorable. |
| 278 return; | 227 return; |
| 279 } | 228 } |
| 280 if (ev.lNetworkEvents & FD_ACCEPT) { | 229 if (ev.lNetworkEvents & FD_ACCEPT) { |
| 281 Accept(); | 230 Accept(); |
| 282 } | 231 } |
| 283 if (ev.lNetworkEvents & FD_READ) { | 232 if (ev.lNetworkEvents & FD_READ) { |
| 284 if (reads_paused_) { | 233 if (reads_paused_) { |
| 285 has_pending_reads_ = true; | 234 has_pending_reads_ = true; |
| 286 } else { | 235 } else { |
| 287 Read(); | 236 Read(); |
| 288 } | 237 } |
| 289 } | 238 } |
| 290 if (ev.lNetworkEvents & FD_CLOSE) { | 239 if (ev.lNetworkEvents & FD_CLOSE) { |
| 291 Close(); | 240 Close(); |
| 292 } | 241 } |
| 293 } | 242 } |
| 294 #elif defined(OS_POSIX) | 243 #elif defined(OS_POSIX) |
| 295 void TCPListenSocket::OnFileCanReadWithoutBlocking(int fd) { | 244 void StreamListenSocket::OnFileCanReadWithoutBlocking(int fd) { |
| 296 switch (wait_state_) { | 245 switch (wait_state_) { |
| 297 case WAITING_ACCEPT: | 246 case WAITING_ACCEPT: |
| 298 Accept(); | 247 Accept(); |
| 299 break; | 248 break; |
| 300 case WAITING_READ: | 249 case WAITING_READ: |
| 301 if (reads_paused_) { | 250 if (reads_paused_) { |
| 302 has_pending_reads_ = true; | 251 has_pending_reads_ = true; |
| 303 } else { | 252 } else { |
| 304 Read(); | 253 Read(); |
| 305 } | 254 } |
| 306 break; | 255 break; |
| 307 default: | 256 default: |
| 308 // Close() is called by Read() in the Linux case. | 257 // Close() is called by Read() in the Linux case. |
| 309 NOTREACHED(); | 258 NOTREACHED(); |
| 310 break; | 259 break; |
| 311 } | 260 } |
| 312 } | 261 } |
| 313 | 262 |
| 314 void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { | 263 void StreamListenSocket::OnFileCanWriteWithoutBlocking(int fd) { |
| 315 // MessagePumpLibevent callback, we don't listen for write events | 264 // MessagePumpLibevent callback, we don't listen for write events |
| 316 // so we shouldn't ever reach here. | 265 // so we shouldn't ever reach here. |
| 317 NOTREACHED(); | 266 NOTREACHED(); |
| 318 } | 267 } |
| 319 | 268 |
| 320 #endif | 269 #endif |
| 321 | 270 |
| 271 void StreamListenSocket::PauseReads() { | |
| 272 DCHECK(!reads_paused_); | |
| 273 reads_paused_ = true; | |
| 274 } | |
| 275 | |
| 276 void StreamListenSocket::ResumeReads() { | |
| 277 DCHECK(reads_paused_); | |
| 278 reads_paused_ = false; | |
| 279 if (has_pending_reads_) { | |
| 280 has_pending_reads_ = false; | |
| 281 Read(); | |
| 282 } | |
| 283 } | |
| 284 | |
| 322 } // namespace net | 285 } // namespace net |
| OLD | NEW |