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