Commit ef2f0027 authored by xiyuan@chromium.org's avatar xiyuan@chromium.org

win: Implement Bluetooth server.

BUG=333979

Review URL: https://codereview.chromium.org/236203018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266831 0039d316-1c4b-4281-b951-d872f2087c98
parent 3c053313
...@@ -72,6 +72,13 @@ class BluetoothAdapterWin : public BluetoothAdapter, ...@@ -72,6 +72,13 @@ class BluetoothAdapterWin : public BluetoothAdapter,
const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices)
OVERRIDE; OVERRIDE;
const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner() const {
return ui_task_runner_;
}
const scoped_refptr<BluetoothSocketThreadWin>& socket_thread() const {
return socket_thread_;
}
protected: protected:
// BluetoothAdapter: // BluetoothAdapter:
virtual void RemovePairingDelegateInternal( virtual void RemovePairingDelegateInternal(
......
...@@ -58,9 +58,9 @@ void BluetoothProfile::Register(const BluetoothUUID& uuid, ...@@ -58,9 +58,9 @@ void BluetoothProfile::Register(const BluetoothUUID& uuid,
profile = CreateBluetoothProfileMac(uuid, options); profile = CreateBluetoothProfileMac(uuid, options);
callback.Run(profile); callback.Run(profile);
#elif defined(OS_WIN) #elif defined(OS_WIN)
BluetoothProfile* profile = NULL; BluetoothProfileWin* profile = NULL;
profile = new BluetoothProfileWin(uuid, options.name); profile = new BluetoothProfileWin();
callback.Run(profile); profile->Init(uuid, options, callback);
#else #else
callback.Run(NULL); callback.Run(NULL);
#endif #endif
......
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
#include "device/bluetooth/bluetooth_profile_win.h" #include "device/bluetooth/bluetooth_profile_win.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_adapter_win.h"
#include "device/bluetooth/bluetooth_device_win.h" #include "device/bluetooth/bluetooth_device_win.h"
#include "device/bluetooth/bluetooth_service_record.h" #include "device/bluetooth/bluetooth_service_record.h"
#include "device/bluetooth/bluetooth_socket_thread_win.h" #include "device/bluetooth/bluetooth_socket_thread_win.h"
...@@ -62,19 +65,36 @@ void OnConnectErrorUI(scoped_refptr<base::SequencedTaskRunner> ui_task_runner, ...@@ -62,19 +65,36 @@ void OnConnectErrorUI(scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
error_callback.Run(error); error_callback.Run(error);
} }
std::string IPEndPointToBluetoothAddress(const net::IPEndPoint& end_point) {
if (end_point.address().size() != net::kBluetoothAddressSize)
return std::string();
// The address is copied from BTH_ADDR field of SOCKADDR_BTH, which is a
// 64-bit ULONGLONG that stores Bluetooth address in little-endian. Print in
// reverse order to preserve the correct ordering.
return base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
end_point.address()[5],
end_point.address()[4],
end_point.address()[3],
end_point.address()[2],
end_point.address()[1],
end_point.address()[0]);
}
} // namespace } // namespace
namespace device { namespace device {
BluetoothProfileWin::BluetoothProfileWin(const BluetoothUUID& uuid, BluetoothProfileWin::BluetoothProfileWin()
const std::string& name) : BluetoothProfile(), rfcomm_channel_(0), weak_ptr_factory_(this) {
: BluetoothProfile(), uuid_(uuid), name_(name) {
} }
BluetoothProfileWin::~BluetoothProfileWin() { BluetoothProfileWin::~BluetoothProfileWin() {
} }
void BluetoothProfileWin::Unregister() { void BluetoothProfileWin::Unregister() {
if (profile_socket_)
profile_socket_->Close();
delete this; delete this;
} }
...@@ -83,6 +103,19 @@ void BluetoothProfileWin::SetConnectionCallback( ...@@ -83,6 +103,19 @@ void BluetoothProfileWin::SetConnectionCallback(
connection_callback_ = callback; connection_callback_ = callback;
} }
void BluetoothProfileWin::Init(const BluetoothUUID& uuid,
const BluetoothProfile::Options& options,
const ProfileCallback& callback) {
uuid_ = uuid;
name_ = options.name;
rfcomm_channel_ = options.channel;
BluetoothAdapterFactory::GetAdapter(
base::Bind(&BluetoothProfileWin::OnGetAdapter,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void BluetoothProfileWin::Connect( void BluetoothProfileWin::Connect(
const BluetoothDeviceWin* device, const BluetoothDeviceWin* device,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner, scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
...@@ -105,9 +138,10 @@ void BluetoothProfileWin::Connect( ...@@ -105,9 +138,10 @@ void BluetoothProfileWin::Connect(
scoped_refptr<BluetoothSocketWin> socket( scoped_refptr<BluetoothSocketWin> socket(
BluetoothSocketWin::CreateBluetoothSocket( BluetoothSocketWin::CreateBluetoothSocket(
*record, ui_task_runner, socket_thread, net_log, source)); ui_task_runner, socket_thread, net_log, source));
socket->Connect(base::Bind(&OnConnectSuccessUI, socket->Connect(*record,
base::Bind(&OnConnectSuccessUI,
ui_task_runner, ui_task_runner,
success_callback, success_callback,
connection_callback_, connection_callback_,
...@@ -116,4 +150,73 @@ void BluetoothProfileWin::Connect( ...@@ -116,4 +150,73 @@ void BluetoothProfileWin::Connect(
error_callback); error_callback);
} }
void BluetoothProfileWin::OnGetAdapter(
const ProfileCallback& callback,
scoped_refptr<BluetoothAdapter> in_adapter) {
DCHECK(!adapter_);
DCHECK(!profile_socket_);
adapter_ = in_adapter;
profile_socket_ = BluetoothSocketWin::CreateBluetoothSocket(
adapter()->ui_task_runner(),
adapter()->socket_thread(),
NULL,
net::NetLog::Source());
profile_socket_->StartService(
uuid_,
name_,
rfcomm_channel_,
base::Bind(&BluetoothProfileWin::OnRegisterProfileSuccess,
weak_ptr_factory_.GetWeakPtr(),
callback),
base::Bind(&BluetoothProfileWin::OnRegisterProfileError,
weak_ptr_factory_.GetWeakPtr(),
callback),
base::Bind(&BluetoothProfileWin::OnNewConnection,
weak_ptr_factory_.GetWeakPtr()));
}
void BluetoothProfileWin::OnRegisterProfileSuccess(
const ProfileCallback& callback) {
callback.Run(this);
}
void BluetoothProfileWin::OnRegisterProfileError(
const ProfileCallback& callback,
const std::string& error_message) {
callback.Run(NULL);
delete this;
}
void BluetoothProfileWin::OnNewConnection(
scoped_refptr<BluetoothSocketWin> connected,
const net::IPEndPoint& peer_address) {
DCHECK(adapter()->ui_task_runner()->RunsTasksOnCurrentThread());
if (connection_callback_.is_null())
return;
std::string device_address = IPEndPointToBluetoothAddress(peer_address);
if (device_address.empty()) {
LOG(WARNING) << "Failed to accept connection for profile "
<< "uuid=" << uuid_.value()
<< ", unexpected peer device address.";
return;
}
BluetoothDevice* device = adapter_->GetDevice(device_address);
if (!device) {
LOG(WARNING) << "Failed to accept connection for profile"
<< ",uuid=" << uuid_.value()
<< ", unknown device=" << device_address;
return;
}
connection_callback_.Run(device, connected);
}
BluetoothAdapterWin* BluetoothProfileWin::adapter() const {
DCHECK(adapter_);
return static_cast<BluetoothAdapterWin*>(adapter_.get());
}
} // namespace device } // namespace device
...@@ -7,23 +7,39 @@ ...@@ -7,23 +7,39 @@
#include <string> #include <string>
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "device/bluetooth/bluetooth_profile.h" #include "device/bluetooth/bluetooth_profile.h"
#include "device/bluetooth/bluetooth_uuid.h" #include "device/bluetooth/bluetooth_uuid.h"
#include "net/base/net_log.h" #include "net/base/net_log.h"
#include "net/socket/tcp_socket.h"
namespace net {
class IPEndPoint;
}
namespace device { namespace device {
class BluetoothAdapter;
class BluetoothAdapterWin;
class BluetoothDeviceWin; class BluetoothDeviceWin;
class BluetoothSocketThreadWin; class BluetoothSocketThreadWin;
class BluetoothSocketWin;
class BluetoothProfileWin : public BluetoothProfile { class BluetoothProfileWin : public BluetoothProfile {
public: public:
typedef base::Callback<void(const std::string&)> ErrorCallback;
// BluetoothProfile override. // BluetoothProfile override.
virtual void Unregister() OVERRIDE; virtual void Unregister() OVERRIDE;
virtual void SetConnectionCallback( virtual void SetConnectionCallback(
const ConnectionCallback& callback) OVERRIDE; const ConnectionCallback& callback) OVERRIDE;
typedef base::Callback<void(const std::string&)> ErrorCallback; // Called by BluetoothProfile::Register to initialize the profile object
// asynchronously.
void Init(const BluetoothUUID& uuid,
const device::BluetoothProfile::Options& options,
const ProfileCallback& callback);
void Connect(const BluetoothDeviceWin* device, void Connect(const BluetoothDeviceWin* device,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner, scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
...@@ -36,13 +52,33 @@ class BluetoothProfileWin : public BluetoothProfile { ...@@ -36,13 +52,33 @@ class BluetoothProfileWin : public BluetoothProfile {
private: private:
friend BluetoothProfile; friend BluetoothProfile;
BluetoothProfileWin(const BluetoothUUID& uuid, const std::string& name); BluetoothProfileWin();
virtual ~BluetoothProfileWin(); virtual ~BluetoothProfileWin();
const BluetoothUUID uuid_; // Internal method run to get the adapter object during initialization.
const std::string name_; void OnGetAdapter(const ProfileCallback& callback,
scoped_refptr<BluetoothAdapter> adapter);
// Callbacks for |profile_socket_|'s StartService call.
void OnRegisterProfileSuccess(const ProfileCallback& callback);
void OnRegisterProfileError(const ProfileCallback& callback,
const std::string& error_message);
// Callback when |profile_socket_| accepts a connection.
void OnNewConnection(scoped_refptr<BluetoothSocketWin> connected,
const net::IPEndPoint& peer_address);
BluetoothAdapterWin* adapter() const;
BluetoothUUID uuid_;
std::string name_;
int rfcomm_channel_;
ConnectionCallback connection_callback_; ConnectionCallback connection_callback_;
scoped_refptr<BluetoothAdapter> adapter_;
scoped_refptr<BluetoothSocketWin> profile_socket_;
base::WeakPtrFactory<BluetoothProfileWin> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BluetoothProfileWin); DISALLOW_COPY_AND_ASSIGN(BluetoothProfileWin);
}; };
......
This diff is collapsed.
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "device/bluetooth/bluetooth_service_record_win.h" #include "device/bluetooth/bluetooth_service_record_win.h"
#include "device/bluetooth/bluetooth_socket.h" #include "device/bluetooth/bluetooth_socket.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_log.h" #include "net/base/net_log.h"
#include "net/socket/tcp_socket.h" #include "net/socket/tcp_socket.h"
...@@ -34,17 +35,32 @@ class BluetoothSocketThreadWin; ...@@ -34,17 +35,32 @@ class BluetoothSocketThreadWin;
// separated thread. // separated thread.
class BluetoothSocketWin : public BluetoothSocket { class BluetoothSocketWin : public BluetoothSocket {
public: public:
typedef base::Callback<void(scoped_refptr<BluetoothSocketWin>,
const net::IPEndPoint&)> OnNewConnectionCallback;
static scoped_refptr<BluetoothSocketWin> CreateBluetoothSocket( static scoped_refptr<BluetoothSocketWin> CreateBluetoothSocket(
const BluetoothServiceRecord& service_record,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner, scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
scoped_refptr<BluetoothSocketThreadWin> socket_thread, scoped_refptr<BluetoothSocketThreadWin> socket_thread,
net::NetLog* net_log, net::NetLog* net_log,
const net::NetLog::Source& source); const net::NetLog::Source& source);
// Connect to the peer device and calls |success_callback| when the // Starts a service with the given uuid, name and rfcomm_channel.
// |success_callback| is invoked when the underlying socket is created
// and the service is published successfully. Otherwise, |error_callback| is
// called with an error message. |new_connection_callback| is invoked when
// an incoming connection is accepted by the underlying socket.
void StartService(
const BluetoothUUID& uuid,
const std::string& name,
int rfcomm_channel,
const base::Closure& success_callback,
const ErrorCompletionCallback& error_callback,
const OnNewConnectionCallback& new_connection_callback);
// connection has been established successfully. If an error occurs, calls // connection has been established successfully. If an error occurs, calls
// |error_callback| with a system error message. // |error_callback| with a system error message.
void Connect(const base::Closure& success_callback, void Connect(const BluetoothServiceRecord& service_record,
const base::Closure& success_callback,
const ErrorCompletionCallback& error_callback); const ErrorCompletionCallback& error_callback);
// Overriden from BluetoothSocket: // Overriden from BluetoothSocket:
...@@ -65,6 +81,8 @@ class BluetoothSocketWin : public BluetoothSocket { ...@@ -65,6 +81,8 @@ class BluetoothSocketWin : public BluetoothSocket {
virtual ~BluetoothSocketWin(); virtual ~BluetoothSocketWin();
private: private:
struct ServiceRegData;
struct WriteRequest { struct WriteRequest {
scoped_refptr<net::IOBuffer> buffer; scoped_refptr<net::IOBuffer> buffer;
int buffer_size; int buffer_size;
...@@ -111,6 +129,17 @@ class BluetoothSocketWin : public BluetoothSocket { ...@@ -111,6 +129,17 @@ class BluetoothSocketWin : public BluetoothSocket {
const ReceiveErrorCompletionCallback& error_callback, const ReceiveErrorCompletionCallback& error_callback,
int send_result); int send_result);
void DoStartService(const BluetoothUUID& uuid,
const std::string& name,
int rfcomm_channel,
const base::Closure& success_callback,
const ErrorCompletionCallback& error_callback,
const OnNewConnectionCallback& new_connection_callback);
void DoAccept();
void OnAcceptOnSocketThread(int accept_result);
void OnAcceptOnUI(scoped_ptr<net::TCPSocket> accept_socket,
const net::IPEndPoint& peer_address);
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
scoped_refptr<BluetoothSocketThreadWin> socket_thread_; scoped_refptr<BluetoothSocketThreadWin> socket_thread_;
net::NetLog* net_log_; net::NetLog* net_log_;
...@@ -125,6 +154,11 @@ class BluetoothSocketWin : public BluetoothSocket { ...@@ -125,6 +154,11 @@ class BluetoothSocketWin : public BluetoothSocket {
std::queue<linked_ptr<WriteRequest> > write_queue_; std::queue<linked_ptr<WriteRequest> > write_queue_;
scoped_refptr<net::IOBufferWithSize> read_buffer_; scoped_refptr<net::IOBufferWithSize> read_buffer_;
scoped_ptr<ServiceRegData> service_reg_data_;
scoped_ptr<net::TCPSocket> accept_socket_;
net::IPEndPoint accept_address_;
OnNewConnectionCallback on_new_connection_callback_;
DISALLOW_COPY_AND_ASSIGN(BluetoothSocketWin); DISALLOW_COPY_AND_ASSIGN(BluetoothSocketWin);
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <windows.h> #include <windows.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#include <winsock2.h> #include <winsock2.h>
#include <ws2bth.h>
#pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "iphlpapi.lib")
#elif defined(OS_POSIX) #elif defined(OS_POSIX)
#include <fcntl.h> #include <fcntl.h>
...@@ -524,13 +525,27 @@ bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr, ...@@ -524,13 +525,27 @@ bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr,
return false; return false;
const struct sockaddr_in6* addr = const struct sockaddr_in6* addr =
reinterpret_cast<const struct sockaddr_in6*>(sock_addr); reinterpret_cast<const struct sockaddr_in6*>(sock_addr);
*address = reinterpret_cast<const unsigned char*>(&addr->sin6_addr); *address = reinterpret_cast<const uint8*>(&addr->sin6_addr);
*address_len = kIPv6AddressSize; *address_len = kIPv6AddressSize;
if (port) if (port)
*port = base::NetToHost16(addr->sin6_port); *port = base::NetToHost16(addr->sin6_port);
return true; return true;
} }
#if defined(OS_WIN)
if (sock_addr->sa_family == AF_BTH) {
if (sock_addr_len < static_cast<socklen_t>(sizeof(SOCKADDR_BTH)))
return false;
const SOCKADDR_BTH* addr =
reinterpret_cast<const SOCKADDR_BTH*>(sock_addr);
*address = reinterpret_cast<const uint8*>(&addr->btAddr);
*address_len = kBluetoothAddressSize;
if (port)
*port = addr->port;
return true;
}
#endif
return false; // Unrecognized |sa_family|. return false; // Unrecognized |sa_family|.
} }
......
...@@ -52,6 +52,10 @@ typedef std::vector<IPAddressNumber> IPAddressList; ...@@ -52,6 +52,10 @@ typedef std::vector<IPAddressNumber> IPAddressList;
static const size_t kIPv4AddressSize = 4; static const size_t kIPv4AddressSize = 4;
static const size_t kIPv6AddressSize = 16; static const size_t kIPv6AddressSize = 16;
#if defined(OS_WIN)
// Bluetooth address size. Windows Bluetooth is supported via winsock.
static const size_t kBluetoothAddressSize = 6;
#endif
// Nothing is ommitted. // Nothing is ommitted.
NET_EXPORT extern const FormatUrlType kFormatUrlOmitNothing; NET_EXPORT extern const FormatUrlType kFormatUrlOmitNothing;
......
...@@ -64,6 +64,28 @@ class TCPSocketTest : public PlatformTest { ...@@ -64,6 +64,28 @@ class TCPSocketTest : public PlatformTest {
*address = IPEndPoint(ip_number, port); *address = IPEndPoint(ip_number, port);
} }
void TestAcceptAsync() {
TestCompletionCallback accept_callback;
scoped_ptr<TCPSocket> accepted_socket;
IPEndPoint accepted_address;
ASSERT_EQ(ERR_IO_PENDING,
socket_.Accept(&accepted_socket, &accepted_address,
accept_callback.callback()));
TestCompletionCallback connect_callback;
TCPClientSocket connecting_socket(local_address_list(),
NULL, NetLog::Source());
connecting_socket.Connect(connect_callback.callback());
EXPECT_EQ(OK, connect_callback.WaitForResult());
EXPECT_EQ(OK, accept_callback.WaitForResult());
EXPECT_TRUE(accepted_socket.get());
// Both sockets should be on the loopback network interface.
EXPECT_EQ(accepted_address.address(), local_address_.address());
}
AddressList local_address_list() const { AddressList local_address_list() const {
return AddressList(local_address_); return AddressList(local_address_);
} }
...@@ -103,27 +125,28 @@ TEST_F(TCPSocketTest, Accept) { ...@@ -103,27 +125,28 @@ TEST_F(TCPSocketTest, Accept) {
// Test Accept() callback. // Test Accept() callback.
TEST_F(TCPSocketTest, AcceptAsync) { TEST_F(TCPSocketTest, AcceptAsync) {
ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4()); ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
TestAcceptAsync();
}
TestCompletionCallback accept_callback; #if defined(OS_WIN)
scoped_ptr<TCPSocket> accepted_socket; // Test Accept() for AdoptListenSocket.
IPEndPoint accepted_address; TEST_F(TCPSocketTest, AcceptForAdoptedListenSocket) {
ASSERT_EQ(ERR_IO_PENDING, // Create a socket to be used with AdoptListenSocket.
socket_.Accept(&accepted_socket, &accepted_address, SOCKET existing_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
accept_callback.callback())); ASSERT_EQ(OK, socket_.AdoptListenSocket(existing_socket));
TestCompletionCallback connect_callback; IPEndPoint address;
TCPClientSocket connecting_socket(local_address_list(), ParseAddress("127.0.0.1", 0, &address);
NULL, NetLog::Source()); SockaddrStorage storage;
connecting_socket.Connect(connect_callback.callback()); ASSERT_TRUE(address.ToSockAddr(storage.addr, &storage.addr_len));
ASSERT_EQ(0, bind(existing_socket, storage.addr, storage.addr_len));
EXPECT_EQ(OK, connect_callback.WaitForResult()); ASSERT_EQ(OK, socket_.Listen(kListenBacklog));
EXPECT_EQ(OK, accept_callback.WaitForResult()); ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
EXPECT_TRUE(accepted_socket.get()); TestAcceptAsync();
// Both sockets should be on the loopback network interface.
EXPECT_EQ(accepted_address.address(), local_address_.address());
} }
#endif
// Accept two connections simultaneously. // Accept two connections simultaneously.
TEST_F(TCPSocketTest, Accept2Connections) { TEST_F(TCPSocketTest, Accept2Connections) {
......
...@@ -322,6 +322,24 @@ int TCPSocketWin::AdoptConnectedSocket(SOCKET socket, ...@@ -322,6 +322,24 @@ int TCPSocketWin::AdoptConnectedSocket(SOCKET socket,
return OK; return OK;
} }
int TCPSocketWin::AdoptListenSocket(SOCKET socket) {
DCHECK(CalledOnValidThread());
DCHECK_EQ(socket_, INVALID_SOCKET);
socket_ = socket;
if (SetNonBlocking(socket_)) {
int result = MapSystemError(WSAGetLastError());
Close();
return result;
}
// |core_| is not needed for sockets that are used to accept connections.
// The operation here is more like Open but with an existing socket.
return OK;
}
int TCPSocketWin::Bind(const IPEndPoint& address) { int TCPSocketWin::Bind(const IPEndPoint& address) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
DCHECK_NE(socket_, INVALID_SOCKET); DCHECK_NE(socket_, INVALID_SOCKET);
......
...@@ -31,8 +31,13 @@ class NET_EXPORT TCPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe), ...@@ -31,8 +31,13 @@ class NET_EXPORT TCPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe),
virtual ~TCPSocketWin(); virtual ~TCPSocketWin();
int Open(AddressFamily family); int Open(AddressFamily family);
// Takes ownership of |socket|.
// Both AdoptConnectedSocket and AdoptListenSocket take ownership of an
// existing socket. AdoptConnectedSocket takes an already connected
// socket. AdoptListenSocket takes a socket that is intended to accept
// connection. In some sense, AdoptListenSocket is more similar to Open.
int AdoptConnectedSocket(SOCKET socket, const IPEndPoint& peer_address); int AdoptConnectedSocket(SOCKET socket, const IPEndPoint& peer_address);
int AdoptListenSocket(SOCKET socket);
int Bind(const IPEndPoint& address); int Bind(const IPEndPoint& address);
......
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