Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1298)

Unified Diff: chrome/browser/extensions/api/socket/tcp_socket.cc

Issue 10827390: Implement chrome.socket.bind/listen/accept for TCP server socket. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unrelated changes. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/socket/tcp_socket.cc
diff --git a/chrome/browser/extensions/api/socket/tcp_socket.cc b/chrome/browser/extensions/api/socket/tcp_socket.cc
index 4eb9b616c0f02440859d95ed7a508b5b71448426..d20cd6e39a38847a7af02c57561c20e2f0c9f0e6 100644
--- a/chrome/browser/extensions/api/socket/tcp_socket.cc
+++ b/chrome/browser/extensions/api/socket/tcp_socket.cc
@@ -14,15 +14,31 @@
namespace extensions {
+const char kTCPSocketTypeInvalidError[] =
+ "Cannot call both connect and listen on the same socket.";
+const char kSocketListenError[] = "Could not listen on the specified port.";
+
TCPSocket::TCPSocket(ApiResourceEventNotifier* event_notifier)
- : Socket(event_notifier) {
+ : Socket(event_notifier),
+ is_client_socket_(false),
+ is_server_socket_(false) {
}
-// For testing.
TCPSocket::TCPSocket(net::TCPClientSocket* tcp_client_socket,
- ApiResourceEventNotifier* event_notifier)
+ ApiResourceEventNotifier* event_notifier,
+ bool is_connected)
: Socket(event_notifier),
- socket_(tcp_client_socket) {
+ socket_(tcp_client_socket),
+ is_client_socket_(true),
+ is_server_socket_(false) {
+ this->is_connected_ = is_connected;
+}
+
+TCPSocket::TCPSocket(net::TCPServerSocket* tcp_server_socket)
+ : Socket(NULL),
+ server_socket_(tcp_server_socket),
+ is_client_socket_(false),
+ is_server_socket_(true) {
}
// static
@@ -32,10 +48,17 @@ TCPSocket* TCPSocket::CreateSocketForTesting(
return new TCPSocket(tcp_client_socket, event_notifier);
}
+// static
+TCPSocket* TCPSocket::CreateServerSocketForTesting(
+ net::TCPServerSocket* tcp_server_socket) {
+ return new TCPSocket(tcp_server_socket);
+}
+
TCPSocket::~TCPSocket() {
if (is_connected_) {
Disconnect();
}
+ server_socket_.reset(NULL);
}
void TCPSocket::Connect(const std::string& address,
@@ -43,10 +66,12 @@ void TCPSocket::Connect(const std::string& address,
const CompletionCallback& callback) {
DCHECK(!callback.is_null());
- if (!connect_callback_.is_null()) {
+ if (!connect_callback_.is_null() || is_server_socket_) {
callback.Run(net::ERR_CONNECTION_FAILED);
return;
}
+ DCHECK(server_socket_.get() == NULL);
Peng 2012/09/11 14:01:18 DCHECK(!server_socket_.get())
justinlin 2012/09/12 07:29:42 Done.
+ is_client_socket_ = true;
connect_callback_ = callback;
int result = net::ERR_CONNECTION_FAILED;
@@ -62,6 +87,15 @@ void TCPSocket::Connect(const std::string& address,
socket_.reset(new net::TCPClientSocket(address_list, NULL,
net::NetLog::Source()));
+
+ if (bind_address_.get() != NULL) {
Peng 2012/09/11 14:01:18 if(bind_address_.get())
justinlin 2012/09/12 07:29:42 Done.
+ if (socket_->Bind(*bind_address_) != 0) {
Peng 2012/09/11 14:01:18 Is there an ERR code for 0? like net::OK
justinlin 2012/09/12 07:29:42 The function explicitly just returns 0, but net::O
+ socket_.reset();
+ OnConnectComplete(net::ERR_ADDRESS_IN_USE);
+ return;
+ };
+ }
+
connect_callback_ = callback;
result = socket_->Connect(base::Bind(
&TCPSocket::OnConnectComplete, base::Unretained(this)));
@@ -77,14 +111,27 @@ void TCPSocket::Disconnect() {
}
int TCPSocket::Bind(const std::string& address, int port) {
- // TODO(penghuang): Supports bind for tcp?
- return net::ERR_FAILED;
+ if (bind_address_.get() != NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ return net::ERR_FAILED;
+ }
+
+ scoped_ptr<net::IPEndPoint> ip_end_point(new net::IPEndPoint());
+ if (!StringAndPortToIPEndPoint(address, port, ip_end_point.get()))
+ return net::ERR_INVALID_ARGUMENT;
+
+ bind_address_.swap(ip_end_point);
+ return net::OK;
}
void TCPSocket::Read(int count,
const ReadCompletionCallback& callback) {
DCHECK(!callback.is_null());
+ if (!is_client_socket_) {
+ callback.Run(net::ERR_FAILED, NULL);
+ return;
+ }
+
if (!read_callback_.is_null()) {
callback.Run(net::ERR_IO_PENDING, NULL);
return;
@@ -140,6 +187,56 @@ bool TCPSocket::SetNoDelay(bool no_delay) {
return socket_->SetNoDelay(no_delay);
}
+int TCPSocket::Listen(int backlog, std::string& error_msg) {
Peng 2012/09/11 14:01:18 I remember our coding style recommend to use poin
justinlin 2012/09/12 07:29:42 Done.
+ if (is_client_socket_) {
+ error_msg = kTCPSocketTypeInvalidError;
+ return net::ERR_NOT_IMPLEMENTED;
+ }
+ DCHECK(socket_.get() == NULL);
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ is_server_socket_ = true;
+
+ if (bind_address_.get() == NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ return net::ERR_FAILED;
+ }
+
+ if (server_socket_.get() == NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ server_socket_.reset(new net::TCPServerSocket(NULL,
+ net::NetLog::Source()));
+ }
+ int result = server_socket_->Listen(*bind_address_, backlog);
+ if (result != 0) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ error_msg = kSocketListenError;
+ }
+ return result;
+}
+
+void TCPSocket::Accept(const AcceptCompletionCallback &callback) {
+ if (!is_server_socket_ || server_socket_.get() == NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ callback.Run(net::ERR_FAILED, NULL);
+ return;
+ }
+
+ // Limits to only 1 blocked accept call.
+ if (!accept_callback_.is_null()) {
+ callback.Run(net::ERR_FAILED, NULL);
+ return;
+ }
+
+ int result = server_socket_->Accept(&accept_socket_, base::Bind(
+ &TCPSocket::OnAccept, base::Unretained(this)));
+ if (result == net::ERR_IO_PENDING) {
+ accept_callback_ = callback;
+ return;
+ } else if (result == net::OK) {
+ accept_callback_ = callback;
+ this->OnAccept(result);
+ return;
+ } else {
+ callback.Run(result, NULL);
+ return;
+ }
+}
+
bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) {
if (!socket_.get())
return false;
@@ -147,9 +244,13 @@ bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) {
}
bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) {
- if (!socket_.get())
+ if (socket_.get() != NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ return !socket_->GetLocalAddress(address);
+ } else if (server_socket_.get() != NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
+ return !server_socket_->GetLocalAddress(address);
+ } else {
return false;
- return !socket_->GetLocalAddress(address);
+ }
}
Socket::SocketType TCPSocket::GetSocketType() const {
@@ -159,7 +260,9 @@ Socket::SocketType TCPSocket::GetSocketType() const {
int TCPSocket::WriteImpl(net::IOBuffer* io_buffer,
int io_buffer_size,
const net::CompletionCallback& callback) {
- if (!socket_.get() || !socket_->IsConnected())
+ if (!is_client_socket_)
+ return net::ERR_FAILED;
+ else if (!socket_.get() || !socket_->IsConnected())
return net::ERR_SOCKET_NOT_CONNECTED;
else
return socket_->Write(io_buffer, io_buffer_size, callback);
@@ -180,4 +283,17 @@ void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
read_callback_.Reset();
}
+void TCPSocket::OnAccept(int result) {
+ DCHECK(!accept_callback_.is_null());
+ if (result == net::OK) {
+ DCHECK(accept_socket_.get() != NULL);
+
+ accept_callback_.Run(
+ result, static_cast<net::TCPClientSocket*>(accept_socket_.release()));
+ } else {
+ accept_callback_.Run(result, NULL);
+ }
+ accept_callback_.Reset();
+}
+
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698