Chromium Code Reviews| Index: remoting/host/websocket_listener.cc |
| diff --git a/remoting/host/websocket_listener.cc b/remoting/host/websocket_listener.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ab48037278feed34680f09665f9bdba7ef6626fc |
| --- /dev/null |
| +++ b/remoting/host/websocket_listener.cc |
| @@ -0,0 +1,96 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "remoting/host/websocket_listener.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/compiler_specific.h" |
| +#include "base/location.h" |
| +#include "base/single_thread_task_runner.h" |
| +#include "base/stl_util.h" |
| +#include "base/sys_byteorder.h" |
| +#include "base/thread_task_runner_handle.h" |
| +#include "net/base/net_errors.h" |
| +#include "net/socket/stream_socket.h" |
| +#include "remoting/host/websocket_connection.h" |
| + |
| +namespace remoting { |
| + |
| +namespace { |
| +const int kTcpListenBacklog = 2; |
|
Wez
2012/11/15 02:28:37
nit: The conventional value for this is 5. Does n
Sergey Ulanov
2012/11/15 21:01:03
Done.
|
| +} // namespace |
| + |
| +WebsocketListener::WebsocketListener() |
| + : tcp_socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())), |
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| +} |
| + |
| +WebsocketListener::~WebsocketListener() { |
| + STLDeleteElements(&pending_connections_); |
| +} |
| + |
| +bool WebsocketListener::Listen(const net::IPEndPoint& address, |
| + const NewConnectionCallback& callback) { |
| + new_connection_callback_ = callback; |
|
Wez
2012/11/15 02:28:37
nit: Blank line after this.
Sergey Ulanov
2012/11/15 21:01:03
Done.
|
| + int result = tcp_socket_->Listen(address, kTcpListenBacklog); |
| + if (result != net::OK) { |
| + return false; |
| + } |
| + |
| + DoAccept(); |
| + return true; |
| +} |
| + |
| +void WebsocketListener::DoAccept() { |
| + while (true) { |
| + int result = tcp_socket_->Accept( |
| + &accepted_socket_, base::Bind(&WebsocketListener::OnAccepted, |
| + base::Unretained(this))); |
| + if (result != net::ERR_IO_PENDING) { |
| + HandleAcceptResult(result); |
| + } |
| + if (result != net::OK) { |
| + break; |
| + } |
| + } |
| +} |
| + |
| +void WebsocketListener::OnAccepted(int result) { |
| + DCHECK_NE(result, net::ERR_IO_PENDING); |
| + if (result == net::OK) { |
| + // The call for WebsocketConnection::Start() may result in delegate being |
| + // called which is allowed to destroyed this object, so we need to post a |
| + // task to call DoAccept() again asynchronously. |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&WebsocketListener::DoAccept, |
| + weak_factory_.GetWeakPtr())); |
| + } |
| + HandleAcceptResult(result); |
| +} |
| + |
| +void WebsocketListener::HandleAcceptResult(int result) { |
| + if (result == net::OK) { |
| + WebsocketConnection* connection = new WebsocketConnection(); |
| + pending_connections_.insert(connection); |
| + connection->Start( |
| + accepted_socket_.Pass(), |
| + base::Bind(&WebsocketListener::OnConnected, weak_factory_.GetWeakPtr(), |
| + connection)); |
| + } else { |
| + LOG(ERROR) << "Error when trying to accept WebSocket connection: " |
| + << result; |
| + } |
| +} |
| + |
| +void WebsocketListener::OnConnected(WebsocketConnection* connection_ptr, |
| + bool handshake_result) { |
| + scoped_ptr<WebsocketConnection> connection(connection_ptr); |
| + pending_connections_.erase(connection_ptr); |
| + if (handshake_result) { |
| + new_connection_callback_.Run(connection.Pass()); |
| + } |
| +} |
| + |
| +} // namespace remoting |