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