Adds socket.getInfo to the socket API

Allows clients to retrieve the state of a specified socket.

BUG=135464
TEST=


Review URL: https://chromiumcodereview.appspot.com/10790137

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150190 0039d316-1c4b-4281-b951-d872f2087c98
parent 25938dab
......@@ -74,6 +74,10 @@ void Socket::OnWriteComplete(int result) {
WriteData();
}
bool Socket::IsConnected() {
return is_connected_;
}
bool Socket::SetKeepAlive(bool enable, int delay) {
return false;
}
......
......@@ -14,6 +14,7 @@
#include "chrome/browser/extensions/api/api_resource.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
namespace net {
class AddressList;
......@@ -63,6 +64,12 @@ class Socket : public ApiResource {
virtual bool SetKeepAlive(bool enable, int delay);
virtual bool SetNoDelay(bool no_delay);
bool IsConnected();
virtual bool IsTCPSocket() = 0;
virtual bool GetPeerAddress(net::IPEndPoint* address) = 0;
virtual bool GetLocalAddress(net::IPEndPoint* address) = 0;
static bool StringAndPortToAddressList(const std::string& ip_address_str,
int port,
net::AddressList* address_list);
......
......@@ -453,4 +453,48 @@ void SocketSetNoDelayFunction::Work() {
SetResult(Value::CreateBooleanValue(result));
}
SocketGetInfoFunction::SocketGetInfoFunction()
: params_(NULL) {}
SocketGetInfoFunction::~SocketGetInfoFunction() {}
bool SocketGetInfoFunction::Prepare() {
params_ = api::socket::GetInfo::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params_.get());
return true;
}
void SocketGetInfoFunction::Work() {
api::socket::SocketInfo info;
Socket* socket = manager_->Get(params_->socket_id);
if (socket) {
// This represents what we know about the socket, and does not call through
// to the system.
info.socket_type = (socket->IsTCPSocket() ? kTCPOption : kUDPOption);
info.connected = socket->IsConnected();
// Grab the peer address as known by the OS. This and the call below will
// always succeed while the socket is connected, even if the socket has
// been remotely closed by the peer; only reading the socket will reveal
// that it should be closed locally.
net::IPEndPoint peerAddress;
if (socket->GetPeerAddress(&peerAddress)) {
info.peer_address.reset(
new std::string(peerAddress.ToStringWithoutPort()));
info.peer_port.reset(new int(peerAddress.port()));
}
// Grab the local address as known by the OS.
net::IPEndPoint localAddress;
if (socket->GetLocalAddress(&localAddress)) {
info.local_address.reset(
new std::string(localAddress.ToStringWithoutPort()));
info.local_port.reset(new int(localAddress.port()));
}
} else {
error_ = kSocketNotFoundError;
}
SetResult(info.ToValue().release());
}
} // namespace extensions
......@@ -279,6 +279,23 @@ class SocketSetNoDelayFunction : public SocketAsyncApiFunction {
scoped_ptr<api::socket::SetNoDelay::Params> params_;
};
class SocketGetInfoFunction : public SocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION_NAME("socket.getInfo");
SocketGetInfoFunction();
protected:
virtual ~SocketGetInfoFunction();
// AsyncApiFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
private:
scoped_ptr<api::socket::GetInfo::Params> params_;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_SOCKET_SOCKET_API_H_
......@@ -140,6 +140,23 @@ bool TCPSocket::SetNoDelay(bool no_delay) {
return socket_->SetNoDelay(no_delay);
}
bool TCPSocket::IsTCPSocket() {
return true;
}
bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) {
if (!socket_.get())
return false;
return !socket_->GetPeerAddress(address);
}
bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) {
if (!socket_.get())
return false;
return !socket_->GetLocalAddress(address);
}
int TCPSocket::WriteImpl(net::IOBuffer* io_buffer,
int io_buffer_size,
const net::CompletionCallback& callback) {
......
......@@ -42,6 +42,9 @@ class TCPSocket : public Socket {
const CompletionCallback& callback) OVERRIDE;
virtual bool SetKeepAlive(bool enable, int delay) OVERRIDE;
virtual bool SetNoDelay(bool no_delay) OVERRIDE;
virtual bool IsTCPSocket() OVERRIDE;
virtual bool GetPeerAddress(net::IPEndPoint* address) OVERRIDE;
virtual bool GetLocalAddress(net::IPEndPoint* address) OVERRIDE;
static TCPSocket* CreateSocketForTesting(
net::TCPClientSocket* tcp_client_socket,
......
......@@ -185,6 +185,18 @@ void UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer,
OnSendToComplete(result);
}
bool UDPSocket::IsTCPSocket() {
return false;
}
bool UDPSocket::GetPeerAddress(net::IPEndPoint* address) {
return !socket_.GetPeerAddress(address);
}
bool UDPSocket::GetLocalAddress(net::IPEndPoint* address) {
return !socket_.GetLocalAddress(address);
}
void UDPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
int result) {
DCHECK(!read_callback_.is_null());
......
......@@ -33,6 +33,9 @@ class UDPSocket : public Socket {
const std::string& address,
int port,
const CompletionCallback& callback) OVERRIDE;
virtual bool IsTCPSocket() OVERRIDE;
virtual bool GetPeerAddress(net::IPEndPoint* address) OVERRIDE;
virtual bool GetLocalAddress(net::IPEndPoint* address) OVERRIDE;
protected:
virtual int WriteImpl(net::IOBuffer* io_buffer,
......
......@@ -53,6 +53,38 @@ namespace socket {
long port;
};
dictionary SocketInfo {
// The type of the passed socket. This will be <code>tcp</code> or
// <code>udp</code>.
SocketType socketType;
// Whether or not the underlying socket is connected.
//
// For <code>tcp</code> sockets, this will remain true even if the remote
// peer has disconnected. Reading or writing to the socket may then result
// in an error, hinting that this socket should be disconnected via
// <code>disconnect()</code>.
//
// For <code>udp</code> sockets, this just represents whether a default
// remote address has been specified for reading and writing packets.
boolean connected;
// If the underlying socket is connected, contains the IPv4/6 address of
// the peer.
DOMString? peerAddress;
// If the underlying socket is connected, contains the port of the
// connected peer.
long? peerPort;
// If the underlying socket is bound or connected, contains its local
// IPv4/6 address.
DOMString? localAddress;
// If the underlying socket is bound or connected, contains its local port.
long? localPort;
};
callback RecvFromCallback = void (RecvFromInfo recvFromInfo);
callback SendToCallback = void (WriteInfo writeInfo);
......@@ -61,6 +93,8 @@ namespace socket {
callback SetNoDelayCallback = void (boolean result);
callback GetInfoCallback = void (SocketInfo result);
interface Functions {
// Creates a socket of the specified type that will connect to the specified
// remote machine.
......@@ -76,7 +110,10 @@ namespace socket {
// |socketId| : The socketId.
static void destroy(long socketId);
// Connects the socket to the remote machine.
// Connects the socket to the remote machine (for a <code>tcp</code>
// socket). For a <code>udp</code> socket, this sets the default address
// which packets are sent to and read from for <code>read()</code>
// and <code>write()</code> calls.
// |socketId| : The socketId.
// |hostname| : The hostname or IP address of the remote machine.
// |port| : The port of the remote machine.
......@@ -141,7 +178,7 @@ namespace socket {
long port,
SendToCallback callback);
// Enable/disable keep-alive functionality for a TCP connection.
// Enables or disables the keep-alive functionality for a TCP connection.
// |socketId| : The socketId.
// |enable| : If true, enable keep-alive functionality.
// |delay| : Set the delay seconds between the last data packet received
......@@ -152,13 +189,20 @@ namespace socket {
optional long delay,
SetKeepAliveCallback callback);
// Enable/disable Nagle algorithm.
// Sets or clears <code>TCP_NODELAY</code> for a TCP connection. Nagle's
// algorithm will be disabled when <code>TCP_NODELAY</code> is set.
// |socketId| : The socketId.
// |noDelay| : If true, disable Nagle algorithm.
// |noDelay| : If true, disables Nagle's algorithm.
// |callback| : Called when the setNoDelay attempt is complete.
static void setNoDelay(long socketId,
boolean noDelay,
SetNoDelayCallback callback);
// Retrieves the state of the given socket.
// |socketId| : The socketId.
// |callback| : Called when the state is available.
static void getInfo(long socketId,
GetInfoCallback callback);
};
};
......@@ -179,6 +179,8 @@
<a href="#method-destroy">destroy</a>
</li><li>
<a href="#method-disconnect">disconnect</a>
</li><li>
<a href="#method-getInfo">getInfo</a>
</li><li>
<a href="#method-read">read</a>
</li><li>
......@@ -221,6 +223,10 @@
<a href="#type-socket.RecvFromInfo">socket.RecvFromInfo</a>
<ol>
</ol>
</li><li>
<a href="#type-experimental.socket.SocketInfo">experimental.socket.SocketInfo</a>
<ol>
</ol>
</li>
</ol>
</li>
......@@ -415,7 +421,7 @@
<var><span>port</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>ConnectCallback</span></var></span>)</div>
<div class="description">
<p>Connects the socket to the remote machine.</p>
<p>Connects the socket to the remote machine (for a <code>tcp</code> socket). For a <code>udp</code> socket, this sets the default address which packets are sent to and read from for <code>read()</code> and <code>write()</code> calls.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
......@@ -758,6 +764,108 @@
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
<!-- RETURNS -->
<dl>
</dl>
<!-- CALLBACK -->
<!-- MIN_VERSION -->
</div> <!-- /description -->
</div><div class="apiItem">
<a name="method-getInfo"></a> <!-- method-anchor -->
<h4>getInfo</h4>
<div class="summary">
<!-- Note: intentionally longer 80 columns -->
<span>chrome.experimental.socket.getInfo</span>(<span class="null"><span>integer</span>
<var><span>socketId</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>GetInfoCallback</span></var></span>)</div>
<div class="description">
<p>Retrieves the state of the given socket.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
<div>
<div>
<dt>
<var>socketId</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>integer</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>The socketId.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>GetInfoCallback</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>function</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
<dd>
<div>
<h5>Parameters</h5>
<dl>
<div>
<div>
<dt>
<var>result</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<a href="experimental.socket.html#type-experimental.socket.SocketInfo">experimental.socket.SocketInfo</a>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
</div>
</dd>
</div>
</div>
</dl>
......@@ -1206,7 +1314,7 @@
<var><span>delay</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>SetKeepAliveCallback</span></var></span>)</div>
<div class="description">
<p>Enable/disable keep-alive functionality for a TCP connection.</p>
<p>Enables or disables the keep-alive functionality for a TCP connection.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
......@@ -1356,7 +1464,7 @@
<var><span>noDelay</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>SetNoDelayCallback</span></var></span>)</div>
<div class="description">
<p>Enable/disable Nagle algorithm.</p>
<p>Sets or clears <code>TCP_NODELAY</code> for a TCP connection. Nagle's algorithm will be disabled when <code>TCP_NODELAY</code> is set.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
......@@ -1400,7 +1508,7 @@
</div>
</em>
</dt>
<dd>If true, disable Nagle algorithm.</dd>
<dd>If true, disables Nagle's algorithm.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
......@@ -1978,6 +2086,179 @@
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div class="apiItem">
<a name="type-experimental.socket.SocketInfo"></a>
<h4>experimental.socket.SocketInfo</h4>
<div>
<dt>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>object</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<dd>
<dl>
<div>
<div>
<dt>
<var>connected</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>boolean</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Whether or not the underlying socket is connected. For <code>tcp</code> sockets, this will remain true even if the remote peer has disconnected. Reading or writing to the socket may then result in an error, hinting that this socket should be disconnected via <code>disconnect()</code>. For <code>udp</code> sockets, this just represents whether a default remote address has been specified for reading and writing packets.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>localAddress</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>string</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is bound or connected, contains its local IPv4/6 address.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>localPort</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>integer</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is bound or connected, contains its local port.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>peerAddress</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>string</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is connected, contains the IPv4/6 address of the peer.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>peerPort</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>integer</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is connected, contains the port of the connected peer.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>socketType</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<a href="experimental.socket.html#type-experimental.socket.SocketType">experimental.socket.SocketType</a>
</span>
</span>
)
</div>
</em>
</dt>
<dd>The type of the passed socket. This will be <code>tcp</code> or <code>udp</code>.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
</dd>
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div> <!-- /apiItem -->
</div> <!-- /apiGroup -->
......
......@@ -210,6 +210,8 @@
<a href="#method-destroy">destroy</a>
</li><li>
<a href="#method-disconnect">disconnect</a>
</li><li>
<a href="#method-getInfo">getInfo</a>
</li><li>
<a href="#method-read">read</a>
</li><li>
......@@ -252,6 +254,10 @@
<a href="#type-socket.RecvFromInfo">RecvFromInfo</a>
<ol>
</ol>
</li><li>
<a href="#type-experimental.socket.SocketInfo">SocketInfo</a>
<ol>
</ol>
</li>
</ol>
</li>
......@@ -485,7 +491,7 @@
<var><span>port</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>ConnectCallback</span></var></span>)</div>
<div class="description">
<p>Connects the socket to the remote machine.</p>
<p>Connects the socket to the remote machine (for a <code>tcp</code> socket). For a <code>udp</code> socket, this sets the default address which packets are sent to and read from for <code>read()</code> and <code>write()</code> calls.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
......@@ -915,6 +921,147 @@
<!-- CALLBACK -->
<!-- MIN_VERSION -->
</div> <!-- /description -->
</div><div class="apiItem">
<a name="method-getInfo"></a> <!-- method-anchor -->
<h4>getInfo</h4>
<div class="summary">
<!-- Note: intentionally longer 80 columns -->
<span>chrome.experimental.socket.getInfo</span>(<span class="null"><span>integer</span>
<var><span>socketId</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>GetInfoCallback</span></var></span>)</div>
<div class="description">
<p>Retrieves the state of the given socket.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
<div>
<div>
<dt>
<var>socketId</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>integer</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>The socketId.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>GetInfoCallback</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>function</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
<dd>
<div>
<h5>Parameters</h5>
<dl>
<div>
<div>
<dt>
<var>result</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<a href="experimental.socket.html#type-experimental.socket.SocketInfo">experimental.socket.SocketInfo</a>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
</div>
</dd>
</div>
</div>
</dl>
<!-- RETURNS -->
<dl>
</dl>
<!-- CALLBACK -->
<div>
<div>
<h4>Callback function</h4>
<p>
The <em>callback</em> parameter should specify a function
that looks like this:
</p>
<!-- Note: intentionally longer 80 columns -->
<pre>function(<span>experimental.socket.SocketInfo result</span>) <span class="subdued">{...}</span>;</pre>
<dl>
<div>
<div>
<dt>
<var>result</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<a href="experimental.socket.html#type-experimental.socket.SocketInfo">experimental.socket.SocketInfo</a>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
</div>
</div>
<!-- MIN_VERSION -->
</div> <!-- /description -->
</div><div class="apiItem">
<a name="method-read"></a> <!-- method-anchor -->
<h4>read</h4>
......@@ -1471,7 +1618,7 @@
<var><span>delay</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>SetKeepAliveCallback</span></var></span>)</div>
<div class="description">
<p>Enable/disable keep-alive functionality for a TCP connection.</p>
<p>Enables or disables the keep-alive functionality for a TCP connection.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
......@@ -1660,7 +1807,7 @@
<var><span>noDelay</span></var></span><span class="null"><span>, </span><span>function</span>
<var><span>SetNoDelayCallback</span></var></span>)</div>
<div class="description">
<p>Enable/disable Nagle algorithm.</p>
<p>Sets or clears <code>TCP_NODELAY</code> for a TCP connection. Nagle's algorithm will be disabled when <code>TCP_NODELAY</code> is set.</p>
<!-- PARAMETERS -->
<h4>Parameters</h4>
<dl>
......@@ -1704,7 +1851,7 @@
</div>
</em>
</dt>
<dd>If true, disable Nagle algorithm.</dd>
<dd>If true, disables Nagle's algorithm.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
......@@ -2360,6 +2507,179 @@
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div class="apiItem">
<a name="type-experimental.socket.SocketInfo"></a>
<h4>experimental.socket.SocketInfo</h4>
<div>
<dt>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>object</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<dd>
<dl>
<div>
<div>
<dt>
<var>connected</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>boolean</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Whether or not the underlying socket is connected. For <code>tcp</code> sockets, this will remain true even if the remote peer has disconnected. Reading or writing to the socket may then result in an error, hinting that this socket should be disconnected via <code>disconnect()</code>. For <code>udp</code> sockets, this just represents whether a default remote address has been specified for reading and writing packets.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>localAddress</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>string</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is bound or connected, contains its local IPv4/6 address.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>localPort</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>integer</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is bound or connected, contains its local port.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>peerAddress</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>string</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is connected, contains the IPv4/6 address of the peer.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>peerPort</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>integer</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>If the underlying socket is connected, contains the port of the connected peer.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>socketType</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<a href="experimental.socket.html#type-experimental.socket.SocketType">experimental.socket.SocketType</a>
</span>
</span>
)
</div>
</em>
</dt>
<dd>The type of the passed socket. This will be <code>tcp</code> or <code>udp</code>.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
</dd>
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div> <!-- /apiItem -->
</div> <!-- /apiGroup -->
......
......@@ -42,8 +42,16 @@ function arrayBuffer2String(buf, callback) {
}
var testSocketCreation = function() {
function onCreate(socketInfo) {
chrome.test.assertTrue(socketInfo.socketId > 0);
function onGetInfo(info) {
chrome.test.assertEq(info.socketType, protocol);
chrome.test.assertFalse(info.connected);
if (info.peerAddress || info.peerPort) {
chrome.test.fail('Unconnected socket should not have peer');
}
if (info.localAddress || info.localPort) {
chrome.test.fail('Unconnected socket should not have local binding');
}
// TODO(miket): this doesn't work yet. It's possible this will become
// automatic, but either way we can't forget to clean up.
......@@ -53,9 +61,21 @@ var testSocketCreation = function() {
chrome.test.succeed();
}
function onCreate(socketInfo) {
chrome.test.assertTrue(socketInfo.socketId > 0);
// Obtaining socket information before a connect() call should be safe, but
// return empty values.
socket.getInfo(socketInfo.socketId, onGetInfo);
}
socket.create(protocol, {}, onCreate);
};
var testGetInfo = function() {
};
function onDataRead(readInfo) {
if (readInfo.resultCode > 0 || readInfo.data.byteLength > 0) {
chrome.test.assertEq(readInfo.resultCode, readInfo.data.byteLength);
......@@ -103,11 +123,37 @@ function onSetNoDelay(result) {
socket.setKeepAlive(socketId, true, 1000, onSetKeepAlive);
}
function onGetInfo(result) {
chrome.test.assertTrue(!!result.localAddress,
"Bound socket should always have local address");
chrome.test.assertTrue(!!result.localPort,
"Bound socket should always have local port");
chrome.test.assertEq(result.socketType, protocol, "Unexpected socketType");
if (protocol == "tcp") {
// NOTE: We're always called with 'localhost', but getInfo will only return
// IPs, not names.
chrome.test.assertEq(result.peerAddress, "127.0.0.1",
"Peer addresss should be the listen server");
chrome.test.assertEq(result.peerPort, port,
"Peer port should be the listen server");
chrome.test.assertTrue(result.connected, "Socket should be connected");
} else {
chrome.test.assertFalse(result.connected, "UDP socket was not connected");
chrome.test.assertTrue(!result.peerAddress,
"Unconnected UDP socket should not have peer address");
chrome.test.assertTrue(!result.peerPort,
"Unconnected UDP socket should not have peer port");
}
socket.setNoDelay(socketId, true, onSetNoDelay);
}
function onConnectOrBindComplete(result) {
chrome.test.assertEq(0, result,
"Connect or bind failed with error " + result);
if (result == 0) {
socket.setNoDelay(socketId, true, onSetNoDelay);
socket.getInfo(socketId, onGetInfo);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment