mirror of
https://github.com/dart-lang/sdk
synced 2024-09-22 18:33:41 +00:00
Add new InternetAddress class with a static lookup function (including IPv6 results).
Socket.connect/ServerSocket.bind now accepts IPv6 host names. If a new ServerSocket is connected to an IPv6 interface, it will (if possible) support incoming IPv4 connections as well. BUG= Review URL: https://codereview.chromium.org//14083007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@21862 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
029e343b42
commit
b33d142414
|
@ -294,7 +294,11 @@ void DebuggerConnectionHandler::StartHandler(const char* address,
|
|||
// listen, accept connections from debuggers, read and handle/dispatch
|
||||
// debugger commands received on these connections.
|
||||
ASSERT(listener_fd_ == -1);
|
||||
listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1);
|
||||
|
||||
OSError *os_error;
|
||||
SocketAddresses* addresses = Socket::LookupAddress(address, -1, &os_error);
|
||||
listener_fd_ = ServerSocket::CreateBindListen(
|
||||
addresses->GetAt(0)->addr(), port_number, 1);
|
||||
DebuggerConnectionImpl::StartHandler(port_number);
|
||||
}
|
||||
|
||||
|
|
|
@ -560,19 +560,17 @@ void SSLFilter::Connect(const char* host_name,
|
|||
|
||||
// SetPeerAddress
|
||||
PRNetAddr host_address;
|
||||
char host_entry_buffer[PR_NETDB_BUF_SIZE];
|
||||
PRHostEnt host_entry;
|
||||
PRStatus rv = PR_GetHostByName(host_name, host_entry_buffer,
|
||||
PR_NETDB_BUF_SIZE, &host_entry);
|
||||
if (rv != PR_SUCCESS) {
|
||||
ThrowPRException("Failed PR_GetHostByName call");
|
||||
PRAddrInfo* info = PR_GetAddrInfoByName(host_name,
|
||||
PR_AF_UNSPEC,
|
||||
PR_AI_ADDRCONFIG);
|
||||
if (info == NULL) {
|
||||
ThrowPRException("Failed PR_GetAddrInfoByName call");
|
||||
}
|
||||
|
||||
int index = PR_EnumerateHostEnt(0, &host_entry, port, &host_address);
|
||||
if (index == -1 || index == 0) {
|
||||
ThrowPRException("Failed PR_EnumerateHostEnt call");
|
||||
}
|
||||
PR_EnumerateAddrInfo(0, info, port, &host_address);
|
||||
|
||||
memio_SetPeerName(filter_, &host_address);
|
||||
PR_FreeAddrInfo(info);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,19 +21,37 @@ int Socket::service_ports_size_ = 0;
|
|||
Dart_Port* Socket::service_ports_ = NULL;
|
||||
int Socket::service_ports_index_ = 0;
|
||||
|
||||
|
||||
static Dart_Handle GetSockAddr(Dart_Handle obj, struct sockaddr_storage* addr) {
|
||||
Dart_TypedData_Type data_type;
|
||||
uint8_t* data = NULL;
|
||||
intptr_t len;
|
||||
Dart_Handle result = Dart_TypedDataAcquireData(
|
||||
obj, &data_type, reinterpret_cast<void**>(&data), &len);
|
||||
if (Dart_IsError(result)) return result;
|
||||
memmove(reinterpret_cast<void *>(addr), data, len);
|
||||
return Dart_Null();
|
||||
}
|
||||
|
||||
|
||||
void FUNCTION_NAME(Socket_CreateConnect)(Dart_NativeArguments args) {
|
||||
Dart_EnterScope();
|
||||
Dart_Handle socket_obj = Dart_GetNativeArgument(args, 0);
|
||||
const char* host = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
|
||||
Dart_Handle host_obj = Dart_GetNativeArgument(args, 1);
|
||||
struct sockaddr_storage addr;
|
||||
Dart_Handle result = GetSockAddr(host_obj, &addr);
|
||||
int64_t port = 0;
|
||||
if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 2), &port)) {
|
||||
intptr_t socket = Socket::CreateConnect(host, port);
|
||||
if (!Dart_IsError(result) &&
|
||||
DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 2), &port)) {
|
||||
intptr_t socket = Socket::CreateConnect(addr, port);
|
||||
OSError error;
|
||||
Dart_TypedDataReleaseData(host_obj);
|
||||
if (socket >= 0) {
|
||||
Dart_Handle err = Socket::SetSocketIdNativeField(socket_obj, socket);
|
||||
if (Dart_IsError(err)) Dart_PropagateError(err);
|
||||
Dart_SetReturnValue(args, Dart_True());
|
||||
} else {
|
||||
Dart_SetReturnValue(args, DartUtils::NewDartOSError());
|
||||
Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
|
||||
}
|
||||
} else {
|
||||
OSError os_error(-1, "Invalid argument", OSError::kUnknown);
|
||||
|
@ -251,7 +269,8 @@ void FUNCTION_NAME(Socket_GetRemotePeer)(Dart_NativeArguments args) {
|
|||
if (Dart_IsError(err)) Dart_PropagateError(err);
|
||||
OSError os_error;
|
||||
intptr_t port = 0;
|
||||
char host[INET_ADDRSTRLEN];
|
||||
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
|
||||
char host[INET6_ADDRSTRLEN];
|
||||
if (Socket::GetRemotePeer(socket, host, &port)) {
|
||||
Dart_Handle list = Dart_NewList(2);
|
||||
Dart_ListSetAt(list, 0, Dart_NewStringFromCString(host));
|
||||
|
@ -310,17 +329,19 @@ void FUNCTION_NAME(Socket_GetStdioHandle)(Dart_NativeArguments args) {
|
|||
void FUNCTION_NAME(ServerSocket_CreateBindListen)(Dart_NativeArguments args) {
|
||||
Dart_EnterScope();
|
||||
Dart_Handle socket_obj = Dart_GetNativeArgument(args, 0);
|
||||
Dart_Handle bind_address_obj = Dart_GetNativeArgument(args, 1);
|
||||
Dart_Handle host_obj = Dart_GetNativeArgument(args, 1);
|
||||
struct sockaddr_storage addr;
|
||||
Dart_Handle result = GetSockAddr(host_obj, &addr);
|
||||
Dart_Handle port_obj = Dart_GetNativeArgument(args, 2);
|
||||
Dart_Handle backlog_obj = Dart_GetNativeArgument(args, 3);
|
||||
int64_t port = 0;
|
||||
int64_t backlog = 0;
|
||||
if (Dart_IsString(bind_address_obj) &&
|
||||
if (!Dart_IsError(result) &&
|
||||
DartUtils::GetInt64Value(port_obj, &port) &&
|
||||
DartUtils::GetInt64Value(backlog_obj, &backlog)) {
|
||||
const char* bind_address = DartUtils::GetStringValue(bind_address_obj);
|
||||
intptr_t socket =
|
||||
ServerSocket::CreateBindListen(bind_address, port, backlog);
|
||||
intptr_t socket = ServerSocket::CreateBindListen(addr, port, backlog);
|
||||
OSError error;
|
||||
Dart_TypedDataReleaseData(host_obj);
|
||||
if (socket >= 0) {
|
||||
Dart_Handle err = Socket::SetSocketIdNativeField(socket_obj, socket);
|
||||
if (Dart_IsError(err)) Dart_PropagateError(err);
|
||||
|
@ -330,7 +351,7 @@ void FUNCTION_NAME(ServerSocket_CreateBindListen)(Dart_NativeArguments args) {
|
|||
OSError os_error(-1, "Invalid host", OSError::kUnknown);
|
||||
Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
|
||||
} else {
|
||||
Dart_SetReturnValue(args, DartUtils::NewDartOSError());
|
||||
Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -366,15 +387,43 @@ void FUNCTION_NAME(ServerSocket_Accept)(Dart_NativeArguments args) {
|
|||
|
||||
|
||||
static CObject* LookupRequest(const CObjectArray& request) {
|
||||
if (request.Length() == 2 && request[1]->IsString()) {
|
||||
if (request.Length() == 3 &&
|
||||
request[1]->IsString() &&
|
||||
request[2]->IsInt32()) {
|
||||
CObjectString host(request[1]);
|
||||
CObjectInt32 type(request[2]);
|
||||
CObject* result = NULL;
|
||||
OSError* os_error = NULL;
|
||||
const char* ip_address =
|
||||
Socket::LookupIPv4Address(host.CString(), &os_error);
|
||||
if (ip_address != NULL) {
|
||||
result = new CObjectString(CObject::NewString(ip_address));
|
||||
free(const_cast<char*>(ip_address));
|
||||
SocketAddresses* addresses =
|
||||
Socket::LookupAddress(host.CString(), type.Value(), &os_error);
|
||||
if (addresses != NULL) {
|
||||
CObjectArray* array = new CObjectArray(
|
||||
CObject::NewArray(addresses->count() + 1));
|
||||
array->SetAt(0, new CObjectInt32(CObject::NewInt32(0)));
|
||||
for (intptr_t i = 0; i < addresses->count(); i++) {
|
||||
SocketAddress* addr = addresses->GetAt(i);
|
||||
CObjectArray* entry = new CObjectArray(CObject::NewArray(3));
|
||||
|
||||
CObjectInt32* type = new CObjectInt32(
|
||||
CObject::NewInt32(addr->GetType()));
|
||||
entry->SetAt(0, type);
|
||||
|
||||
CObjectString* as_string = new CObjectString(CObject::NewString(
|
||||
addr->as_string()));
|
||||
entry->SetAt(1, as_string);
|
||||
|
||||
sockaddr_storage raw = addr->addr();
|
||||
CObjectUint8Array* data = new CObjectUint8Array(CObject::NewUint8Array(
|
||||
SocketAddress::GetAddrLength(raw)));
|
||||
memmove(data->Buffer(),
|
||||
reinterpret_cast<void *>(&raw),
|
||||
SocketAddress::GetAddrLength(raw));
|
||||
|
||||
entry->SetAt(2, data);
|
||||
array->SetAt(i + 1, entry);
|
||||
}
|
||||
result = array;
|
||||
delete addresses;
|
||||
} else {
|
||||
result = CObject::NewOSError(os_error);
|
||||
delete os_error;
|
||||
|
|
|
@ -23,6 +23,66 @@
|
|||
#error Unknown target os.
|
||||
#endif
|
||||
|
||||
class SocketAddress {
|
||||
public:
|
||||
enum {
|
||||
TYPE_ANY = -1,
|
||||
TYPE_IPV4,
|
||||
TYPE_IPV6,
|
||||
};
|
||||
|
||||
explicit SocketAddress(struct addrinfo* addrinfo);
|
||||
|
||||
int GetType() {
|
||||
if (addr_.ss_family == AF_INET6) return TYPE_IPV6;
|
||||
return TYPE_IPV4;
|
||||
}
|
||||
|
||||
const char* as_string() const { return as_string_; }
|
||||
const sockaddr_storage& addr() const { return addr_; }
|
||||
|
||||
static intptr_t GetAddrLength(const sockaddr_storage& addr) {
|
||||
return addr.ss_family == AF_INET6 ?
|
||||
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
static int16_t FromType(int type) {
|
||||
if (type == TYPE_ANY) return AF_UNSPEC;
|
||||
if (type == TYPE_IPV4) return AF_INET;
|
||||
ASSERT(type == TYPE_IPV6 && "Invalid type");
|
||||
return AF_INET6;
|
||||
}
|
||||
|
||||
private:
|
||||
char as_string_[INET6_ADDRSTRLEN];
|
||||
sockaddr_storage addr_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SocketAddress);
|
||||
};
|
||||
|
||||
class SocketAddresses {
|
||||
public:
|
||||
explicit SocketAddresses(intptr_t count)
|
||||
: count_(count),
|
||||
addresses_(new SocketAddress*[count_]) {}
|
||||
|
||||
~SocketAddresses() {
|
||||
for (intptr_t i = 0; i < count_; i++) {
|
||||
delete addresses_[i];
|
||||
}
|
||||
delete[] addresses_;
|
||||
}
|
||||
|
||||
intptr_t count() const { return count_; }
|
||||
SocketAddress* GetAt(intptr_t i) const { return addresses_[i]; }
|
||||
void SetAt(intptr_t i, SocketAddress* addr) { addresses_[i] = addr; }
|
||||
|
||||
private:
|
||||
const intptr_t count_;
|
||||
SocketAddress** addresses_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SocketAddresses);
|
||||
};
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
|
@ -34,7 +94,8 @@ class Socket {
|
|||
static intptr_t Available(intptr_t fd);
|
||||
static int Read(intptr_t fd, void* buffer, intptr_t num_bytes);
|
||||
static int Write(intptr_t fd, const void* buffer, intptr_t num_bytes);
|
||||
static intptr_t CreateConnect(const char* host, const intptr_t port);
|
||||
static intptr_t CreateConnect(sockaddr_storage addr,
|
||||
const intptr_t port);
|
||||
static intptr_t GetPort(intptr_t fd);
|
||||
static bool GetRemotePeer(intptr_t fd, char* host, intptr_t* port);
|
||||
static void GetError(intptr_t fd, OSError* os_error);
|
||||
|
@ -45,9 +106,10 @@ class Socket {
|
|||
static bool SetBlocking(intptr_t fd);
|
||||
static bool SetNoDelay(intptr_t fd, bool enabled);
|
||||
|
||||
// Perform a IPv4 hostname lookup. Returns the hostname string in
|
||||
// IPv4 dotted-decimal format.
|
||||
static const char* LookupIPv4Address(char* host, OSError** os_error);
|
||||
// Perform a hostname lookup. Returns the SocketAddresses.
|
||||
static SocketAddresses* LookupAddress(const char* host,
|
||||
int type,
|
||||
OSError** os_error);
|
||||
|
||||
static Dart_Port GetServicePort();
|
||||
|
||||
|
@ -76,7 +138,7 @@ class ServerSocket {
|
|||
//
|
||||
// -1: system error (errno set)
|
||||
// -5: invalid bindAddress
|
||||
static intptr_t CreateBindListen(const char* bindAddress,
|
||||
static intptr_t CreateBindListen(sockaddr_storage addr,
|
||||
intptr_t port,
|
||||
intptr_t backlog);
|
||||
|
||||
|
|
|
@ -17,18 +17,44 @@
|
|||
#include "bin/log.h"
|
||||
|
||||
|
||||
#define SOCKADDR_STORAGE_SET_PORT(addr, port) \
|
||||
if (addr.ss_family == AF_INET) { \
|
||||
reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port = htons(port); \
|
||||
} else { \
|
||||
reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port = htons(port); \
|
||||
}
|
||||
|
||||
|
||||
#define SOCKADDR_STORAGE_GET_PORT(addr) \
|
||||
addr.ss_family == AF_INET ? \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port) : \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port)
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
|
||||
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
|
||||
sockaddr_in *sockaddr = reinterpret_cast<sockaddr_in *>(addrinfo->ai_addr);
|
||||
const char* result = inet_ntop(addrinfo->ai_family,
|
||||
&sockaddr->sin_addr,
|
||||
as_string_,
|
||||
INET6_ADDRSTRLEN);
|
||||
if (result == NULL) as_string_[0] = 0;
|
||||
memmove(reinterpret_cast<void *>(&addr_),
|
||||
addrinfo->ai_addr,
|
||||
addrinfo->ai_addrlen);
|
||||
}
|
||||
|
||||
|
||||
bool Socket::Initialize() {
|
||||
// Nothing to do on Android.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
||||
intptr_t Socket::CreateConnect(sockaddr_storage addr, const intptr_t port) {
|
||||
intptr_t fd;
|
||||
struct hostent* server;
|
||||
struct sockaddr_in server_address;
|
||||
|
||||
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
|
||||
fd = TEMP_FAILURE_RETRY(socket(addr.ss_family, SOCK_STREAM, 0));
|
||||
if (fd < 0) {
|
||||
Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
|
||||
return -1;
|
||||
|
@ -37,24 +63,15 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
|||
FDUtils::SetCloseOnExec(fd);
|
||||
Socket::SetNonBlocking(fd);
|
||||
|
||||
server = gethostbyname(host);
|
||||
if (server == NULL) {
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_port = htons(port);
|
||||
bcopy(server->h_addr, &server_address.sin_addr.s_addr, server->h_length);
|
||||
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
intptr_t result = TEMP_FAILURE_RETRY(
|
||||
connect(fd,
|
||||
reinterpret_cast<struct sockaddr *>(&server_address),
|
||||
sizeof(server_address)));
|
||||
reinterpret_cast<struct sockaddr*>(&addr),
|
||||
SocketAddress::GetAddrLength(addr)));
|
||||
if (result == 0 || errno == EINPROGRESS) {
|
||||
return fd;
|
||||
}
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -92,7 +109,7 @@ int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
|
|||
|
||||
intptr_t Socket::GetPort(intptr_t fd) {
|
||||
ASSERT(fd >= 0);
|
||||
struct sockaddr_in socket_address;
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
getsockname(fd,
|
||||
|
@ -101,13 +118,13 @@ intptr_t Socket::GetPort(intptr_t fd) {
|
|||
Log::PrintErr("Error getsockname: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return ntohs(socket_address.sin_port);
|
||||
return SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
||||
ASSERT(fd >= 0);
|
||||
struct sockaddr_in socket_address;
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
getpeername(fd,
|
||||
|
@ -116,14 +133,24 @@ bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
|||
Log::PrintErr("Error getpeername: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (inet_ntop(socket_address.sin_family,
|
||||
reinterpret_cast<const void *>(&socket_address.sin_addr),
|
||||
const void* src;
|
||||
if (socket_address.ss_family == AF_INET6) {
|
||||
const sockaddr_in6* in6 =
|
||||
reinterpret_cast<const sockaddr_in6*>(&socket_address);
|
||||
src = reinterpret_cast<const void*>(&in6->sin6_addr);
|
||||
} else {
|
||||
const sockaddr_in* in =
|
||||
reinterpret_cast<const sockaddr_in*>(&socket_address);
|
||||
src = reinterpret_cast<const void*>(&in->sin_addr);
|
||||
}
|
||||
if (inet_ntop(socket_address.ss_family,
|
||||
src,
|
||||
host,
|
||||
INET_ADDRSTRLEN) == NULL) {
|
||||
Log::PrintErr("Error inet_ntop: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
*port = ntohs(socket_address.sin_port);
|
||||
*port = SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -145,12 +172,15 @@ intptr_t Socket::GetStdioHandle(int num) {
|
|||
}
|
||||
|
||||
|
||||
const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
||||
// Perform a name lookup for an IPv4 address.
|
||||
SocketAddresses* Socket::LookupAddress(const char* host,
|
||||
int type,
|
||||
OSError** os_error) {
|
||||
// Perform a name lookup for a host name.
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_family = SocketAddress::FromType(type);
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = 0;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
struct addrinfo* info = NULL;
|
||||
int status = getaddrinfo(host, 0, &hints, &info);
|
||||
|
@ -161,38 +191,30 @@ const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
|||
OSError::kGetAddressInfo);
|
||||
return NULL;
|
||||
}
|
||||
// Convert the address into IPv4 dotted decimal notation.
|
||||
char* buffer = reinterpret_cast<char*>(malloc(INET_ADDRSTRLEN));
|
||||
sockaddr_in *sockaddr = reinterpret_cast<sockaddr_in *>(info->ai_addr);
|
||||
const char* result = inet_ntop(AF_INET,
|
||||
reinterpret_cast<void *>(&sockaddr->sin_addr),
|
||||
buffer,
|
||||
INET_ADDRSTRLEN);
|
||||
if (result == NULL) {
|
||||
free(buffer);
|
||||
return NULL;
|
||||
intptr_t count = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
|
||||
}
|
||||
ASSERT(result == buffer);
|
||||
return buffer;
|
||||
SocketAddresses* addresses = new SocketAddresses(count);
|
||||
intptr_t i = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
|
||||
addresses->SetAt(i, new SocketAddress(c));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(info);
|
||||
return addresses;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ServerSocket::CreateBindListen(const char* host,
|
||||
intptr_t ServerSocket::CreateBindListen(sockaddr_storage addr,
|
||||
intptr_t port,
|
||||
intptr_t backlog) {
|
||||
intptr_t fd;
|
||||
struct sockaddr_in server_address;
|
||||
|
||||
in_addr_t s_addr = inet_addr(host);
|
||||
if (s_addr == INADDR_NONE) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
|
||||
if (fd < 0) {
|
||||
Log::PrintErr("Error CreateBind: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fd = TEMP_FAILURE_RETRY(socket(addr.ss_family, SOCK_STREAM, 0));
|
||||
if (fd < 0) return -1;
|
||||
|
||||
FDUtils::SetCloseOnExec(fd);
|
||||
|
||||
|
@ -200,22 +222,23 @@ intptr_t ServerSocket::CreateBindListen(const char* host,
|
|||
TEMP_FAILURE_RETRY(
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
|
||||
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_port = htons(port);
|
||||
server_address.sin_addr.s_addr = s_addr;
|
||||
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
|
||||
if (addr.ss_family == AF_INET6) {
|
||||
optval = 0;
|
||||
TEMP_FAILURE_RETRY(
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
bind(fd,
|
||||
reinterpret_cast<struct sockaddr *>(&server_address),
|
||||
sizeof(server_address))) < 0) {
|
||||
reinterpret_cast<struct sockaddr*>(&addr),
|
||||
SocketAddress::GetAddrLength(addr))) < 0) {
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
Log::PrintErr("Error Bind: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY(listen(fd, backlog)) != 0) {
|
||||
Log::PrintErr("Error Listen: %s\n", strerror(errno));
|
||||
if (TEMP_FAILURE_RETRY(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,18 +19,44 @@
|
|||
#include "bin/socket.h"
|
||||
|
||||
|
||||
#define SOCKADDR_STORAGE_SET_PORT(addr, port) \
|
||||
if (addr.ss_family == AF_INET) { \
|
||||
reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port = htons(port); \
|
||||
} else { \
|
||||
reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port = htons(port); \
|
||||
}
|
||||
|
||||
|
||||
#define SOCKADDR_STORAGE_GET_PORT(addr) \
|
||||
addr.ss_family == AF_INET ? \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port) : \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port)
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
|
||||
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
|
||||
sockaddr_in *sockaddr = reinterpret_cast<sockaddr_in *>(addrinfo->ai_addr);
|
||||
const char* result = inet_ntop(addrinfo->ai_family,
|
||||
&sockaddr->sin_addr,
|
||||
as_string_,
|
||||
INET6_ADDRSTRLEN);
|
||||
if (result == NULL) as_string_[0] = 0;
|
||||
memmove(reinterpret_cast<void *>(&addr_),
|
||||
addrinfo->ai_addr,
|
||||
addrinfo->ai_addrlen);
|
||||
}
|
||||
|
||||
|
||||
bool Socket::Initialize() {
|
||||
// Nothing to do on Linux.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
||||
intptr_t Socket::CreateConnect(sockaddr_storage addr, const intptr_t port) {
|
||||
intptr_t fd;
|
||||
struct hostent server;
|
||||
struct sockaddr_in server_address;
|
||||
|
||||
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
|
||||
fd = TEMP_FAILURE_RETRY(socket(addr.ss_family, SOCK_STREAM, 0));
|
||||
if (fd < 0) {
|
||||
Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
|
||||
return -1;
|
||||
|
@ -39,28 +65,15 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
|||
FDUtils::SetCloseOnExec(fd);
|
||||
Socket::SetNonBlocking(fd);
|
||||
|
||||
static const size_t kTempBufSize = 1024;
|
||||
char temp_buf[kTempBufSize];
|
||||
struct hostent *unused;
|
||||
int err;
|
||||
if (gethostbyname_r(
|
||||
host, &server, temp_buf, kTempBufSize, &unused, &err) != 0) {
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_port = htons(port);
|
||||
bcopy(server.h_addr, &server_address.sin_addr.s_addr, server.h_length);
|
||||
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
intptr_t result = TEMP_FAILURE_RETRY(
|
||||
connect(fd,
|
||||
reinterpret_cast<struct sockaddr *>(&server_address),
|
||||
sizeof(server_address)));
|
||||
reinterpret_cast<struct sockaddr*>(&addr),
|
||||
SocketAddress::GetAddrLength(addr)));
|
||||
if (result == 0 || errno == EINPROGRESS) {
|
||||
return fd;
|
||||
}
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -98,7 +111,7 @@ int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
|
|||
|
||||
intptr_t Socket::GetPort(intptr_t fd) {
|
||||
ASSERT(fd >= 0);
|
||||
struct sockaddr_in socket_address;
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
getsockname(fd,
|
||||
|
@ -107,13 +120,13 @@ intptr_t Socket::GetPort(intptr_t fd) {
|
|||
Log::PrintErr("Error getsockname: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return ntohs(socket_address.sin_port);
|
||||
return SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
||||
ASSERT(fd >= 0);
|
||||
struct sockaddr_in socket_address;
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
getpeername(fd,
|
||||
|
@ -122,14 +135,24 @@ bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
|||
Log::PrintErr("Error getpeername: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (inet_ntop(socket_address.sin_family,
|
||||
reinterpret_cast<const void *>(&socket_address.sin_addr),
|
||||
const void* src;
|
||||
if (socket_address.ss_family == AF_INET6) {
|
||||
const sockaddr_in6* in6 =
|
||||
reinterpret_cast<const sockaddr_in6*>(&socket_address);
|
||||
src = reinterpret_cast<const void*>(&in6->sin6_addr);
|
||||
} else {
|
||||
const sockaddr_in* in =
|
||||
reinterpret_cast<const sockaddr_in*>(&socket_address);
|
||||
src = reinterpret_cast<const void*>(&in->sin_addr);
|
||||
}
|
||||
if (inet_ntop(socket_address.ss_family,
|
||||
src,
|
||||
host,
|
||||
INET_ADDRSTRLEN) == NULL) {
|
||||
Log::PrintErr("Error inet_ntop: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
*port = ntohs(socket_address.sin_port);
|
||||
*port = SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -161,12 +184,15 @@ intptr_t Socket::GetStdioHandle(int num) {
|
|||
}
|
||||
|
||||
|
||||
const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
||||
// Perform a name lookup for an IPv4 address.
|
||||
SocketAddresses* Socket::LookupAddress(const char* host,
|
||||
int type,
|
||||
OSError** os_error) {
|
||||
// Perform a name lookup for a host name.
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_family = SocketAddress::FromType(type);
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = 0;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
struct addrinfo* info = NULL;
|
||||
int status = getaddrinfo(host, 0, &hints, &info);
|
||||
|
@ -177,34 +203,29 @@ const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
|||
OSError::kGetAddressInfo);
|
||||
return NULL;
|
||||
}
|
||||
// Convert the address into IPv4 dotted decimal notation.
|
||||
char* buffer = reinterpret_cast<char*>(malloc(INET_ADDRSTRLEN));
|
||||
sockaddr_in *sockaddr = reinterpret_cast<sockaddr_in *>(info->ai_addr);
|
||||
const char* result = inet_ntop(AF_INET,
|
||||
reinterpret_cast<void *>(&sockaddr->sin_addr),
|
||||
buffer,
|
||||
INET_ADDRSTRLEN);
|
||||
if (result == NULL) {
|
||||
free(buffer);
|
||||
return NULL;
|
||||
intptr_t count = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
|
||||
}
|
||||
ASSERT(result == buffer);
|
||||
return buffer;
|
||||
SocketAddresses* addresses = new SocketAddresses(count);
|
||||
intptr_t i = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
|
||||
addresses->SetAt(i, new SocketAddress(c));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(info);
|
||||
return addresses;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ServerSocket::CreateBindListen(const char* host,
|
||||
intptr_t ServerSocket::CreateBindListen(sockaddr_storage addr,
|
||||
intptr_t port,
|
||||
intptr_t backlog) {
|
||||
intptr_t fd;
|
||||
struct sockaddr_in server_address;
|
||||
|
||||
in_addr_t s_addr = inet_addr(host);
|
||||
if (s_addr == INADDR_NONE) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
|
||||
fd = TEMP_FAILURE_RETRY(socket(addr.ss_family, SOCK_STREAM, 0));
|
||||
if (fd < 0) return -1;
|
||||
|
||||
FDUtils::SetCloseOnExec(fd);
|
||||
|
@ -213,15 +234,17 @@ intptr_t ServerSocket::CreateBindListen(const char* host,
|
|||
TEMP_FAILURE_RETRY(
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
|
||||
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_port = htons(port);
|
||||
server_address.sin_addr.s_addr = s_addr;
|
||||
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
|
||||
if (addr.ss_family == AF_INET6) {
|
||||
optval = 0;
|
||||
TEMP_FAILURE_RETRY(
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
bind(fd,
|
||||
reinterpret_cast<struct sockaddr *>(&server_address),
|
||||
sizeof(server_address))) < 0) {
|
||||
reinterpret_cast<struct sockaddr*>(&addr),
|
||||
SocketAddress::GetAddrLength(addr))) < 0) {
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -19,18 +19,44 @@
|
|||
#include "bin/socket.h"
|
||||
|
||||
|
||||
#define SOCKADDR_STORAGE_SET_PORT(addr, port) \
|
||||
if (addr.ss_family == AF_INET) { \
|
||||
reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port = htons(port); \
|
||||
} else { \
|
||||
reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port = htons(port); \
|
||||
}
|
||||
|
||||
|
||||
#define SOCKADDR_STORAGE_GET_PORT(addr) \
|
||||
addr.ss_family == AF_INET ? \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port) : \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port)
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
|
||||
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
|
||||
sockaddr_in *sockaddr = reinterpret_cast<sockaddr_in *>(addrinfo->ai_addr);
|
||||
const char* result = inet_ntop(addrinfo->ai_family,
|
||||
&sockaddr->sin_addr,
|
||||
as_string_,
|
||||
INET6_ADDRSTRLEN);
|
||||
if (result == NULL) as_string_[0] = 0;
|
||||
memmove(reinterpret_cast<void *>(&addr_),
|
||||
addrinfo->ai_addr,
|
||||
addrinfo->ai_addrlen);
|
||||
}
|
||||
|
||||
|
||||
bool Socket::Initialize() {
|
||||
// Nothing to do on Mac OS.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
||||
intptr_t Socket::CreateConnect(sockaddr_storage addr, const intptr_t port) {
|
||||
intptr_t fd;
|
||||
struct hostent* server;
|
||||
struct sockaddr_in server_address;
|
||||
|
||||
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
|
||||
fd = TEMP_FAILURE_RETRY(socket(addr.ss_family, SOCK_STREAM, 0));
|
||||
if (fd < 0) {
|
||||
Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
|
||||
return -1;
|
||||
|
@ -39,24 +65,15 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
|||
FDUtils::SetCloseOnExec(fd);
|
||||
Socket::SetNonBlocking(fd);
|
||||
|
||||
server = gethostbyname(host);
|
||||
if (server == NULL) {
|
||||
VOID_TEMP_FAILURE_RETRY(close(fd));
|
||||
Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_port = htons(port);
|
||||
bcopy(server->h_addr, &server_address.sin_addr.s_addr, server->h_length);
|
||||
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
intptr_t result = TEMP_FAILURE_RETRY(
|
||||
connect(fd,
|
||||
reinterpret_cast<struct sockaddr *>(&server_address),
|
||||
sizeof(server_address)));
|
||||
reinterpret_cast<struct sockaddr*>(&addr),
|
||||
SocketAddress::GetAddrLength(addr)));
|
||||
if (result == 0 || errno == EINPROGRESS) {
|
||||
return fd;
|
||||
}
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -94,7 +111,7 @@ int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
|
|||
|
||||
intptr_t Socket::GetPort(intptr_t fd) {
|
||||
ASSERT(fd >= 0);
|
||||
struct sockaddr_in socket_address;
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
getsockname(fd,
|
||||
|
@ -103,13 +120,13 @@ intptr_t Socket::GetPort(intptr_t fd) {
|
|||
Log::PrintErr("Error getsockname: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return ntohs(socket_address.sin_port);
|
||||
return SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
||||
ASSERT(fd >= 0);
|
||||
struct sockaddr_in socket_address;
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
getpeername(fd,
|
||||
|
@ -118,14 +135,24 @@ bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
|||
Log::PrintErr("Error getpeername: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (inet_ntop(socket_address.sin_family,
|
||||
reinterpret_cast<const void *>(&socket_address.sin_addr),
|
||||
const void* src;
|
||||
if (socket_address.ss_family == AF_INET6) {
|
||||
const sockaddr_in6* in6 =
|
||||
reinterpret_cast<const sockaddr_in6*>(&socket_address);
|
||||
src = reinterpret_cast<const void*>(&in6->sin6_addr);
|
||||
} else {
|
||||
const sockaddr_in* in =
|
||||
reinterpret_cast<const sockaddr_in*>(&socket_address);
|
||||
src = reinterpret_cast<const void*>(&in->sin_addr);
|
||||
}
|
||||
if (inet_ntop(socket_address.ss_family,
|
||||
src,
|
||||
host,
|
||||
INET_ADDRSTRLEN) == NULL) {
|
||||
Log::PrintErr("Error inet_ntop: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
*port = ntohs(socket_address.sin_port);
|
||||
*port = SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -157,12 +184,15 @@ intptr_t Socket::GetStdioHandle(int num) {
|
|||
}
|
||||
|
||||
|
||||
const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
||||
// Perform a name lookup for an IPv4 address.
|
||||
SocketAddresses* Socket::LookupAddress(const char* host,
|
||||
int type,
|
||||
OSError** os_error) {
|
||||
// Perform a name lookup for a host name.
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_family = SocketAddress::FromType(type);
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = 0;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
struct addrinfo* info = NULL;
|
||||
int status = getaddrinfo(host, 0, &hints, &info);
|
||||
|
@ -173,34 +203,29 @@ const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
|||
OSError::kGetAddressInfo);
|
||||
return NULL;
|
||||
}
|
||||
// Convert the address into IPv4 dotted decimal notation.
|
||||
char* buffer = reinterpret_cast<char*>(malloc(INET_ADDRSTRLEN));
|
||||
sockaddr_in *sockaddr = reinterpret_cast<sockaddr_in *>(info->ai_addr);
|
||||
const char* result = inet_ntop(AF_INET,
|
||||
reinterpret_cast<void *>(&sockaddr->sin_addr),
|
||||
buffer,
|
||||
INET_ADDRSTRLEN);
|
||||
if (result == NULL) {
|
||||
free(buffer);
|
||||
return NULL;
|
||||
intptr_t count = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
|
||||
}
|
||||
ASSERT(result == buffer);
|
||||
return buffer;
|
||||
SocketAddresses* addresses = new SocketAddresses(count);
|
||||
intptr_t i = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
|
||||
addresses->SetAt(i, new SocketAddress(c));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(info);
|
||||
return addresses;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ServerSocket::CreateBindListen(const char* host,
|
||||
intptr_t ServerSocket::CreateBindListen(sockaddr_storage addr,
|
||||
intptr_t port,
|
||||
intptr_t backlog) {
|
||||
intptr_t fd;
|
||||
struct sockaddr_in server_address;
|
||||
|
||||
in_addr_t s_addr = inet_addr(host);
|
||||
if (s_addr == INADDR_NONE) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
|
||||
fd = TEMP_FAILURE_RETRY(socket(addr.ss_family, SOCK_STREAM, 0));
|
||||
if (fd < 0) return -1;
|
||||
|
||||
FDUtils::SetCloseOnExec(fd);
|
||||
|
@ -209,15 +234,17 @@ intptr_t ServerSocket::CreateBindListen(const char* host,
|
|||
VOID_TEMP_FAILURE_RETRY(
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
|
||||
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_port = htons(port);
|
||||
server_address.sin_addr.s_addr = s_addr;
|
||||
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
|
||||
if (addr.ss_family == AF_INET6) {
|
||||
optval = 0;
|
||||
VOID_TEMP_FAILURE_RETRY(
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
if (TEMP_FAILURE_RETRY(
|
||||
bind(fd,
|
||||
reinterpret_cast<struct sockaddr *>(&server_address),
|
||||
sizeof(server_address))) < 0) {
|
||||
reinterpret_cast<struct sockaddr*>(&addr),
|
||||
SocketAddress::GetAddrLength(addr))) < 0) {
|
||||
VOID_TEMP_FAILURE_RETRY(close(fd));
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -12,12 +12,36 @@ patch class RawServerSocket {
|
|||
|
||||
|
||||
patch class RawSocket {
|
||||
/* patch */ static Future<RawSocket> connect(String host, int port) {
|
||||
/* patch */ static Future<RawSocket> connect(host, int port) {
|
||||
return _RawSocket.connect(host, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
patch class InternetAddress {
|
||||
/* patch */ static Future<List<InternetAddress>> lookup(
|
||||
String host, {InternetAddressType type: InternetAddressType.ANY}) {
|
||||
return _NativeSocket.lookup(host, type: type);
|
||||
}
|
||||
}
|
||||
|
||||
class _InternetAddress implements InternetAddress {
|
||||
final InternetAddressType type;
|
||||
final String address;
|
||||
final String host;
|
||||
final Uint8List _sockaddr_storage;
|
||||
|
||||
_InternetAddress(InternetAddressType this.type,
|
||||
String this.address,
|
||||
String this.host,
|
||||
List<int> this._sockaddr_storage);
|
||||
|
||||
String toString() {
|
||||
return "InternetAddress('$address', ${type.name})";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The _NativeSocket class encapsulates an OS socket.
|
||||
class _NativeSocket extends NativeFieldWrapperClass1 {
|
||||
// Bit flags used when communicating between the eventhandler and
|
||||
|
@ -74,57 +98,91 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
|||
// Holds the port of the socket, null if not known.
|
||||
int localPort;
|
||||
|
||||
// Holds the host or address used to connect or bind the socket.
|
||||
String localHost;
|
||||
// Holds the address used to connect or bind the socket.
|
||||
InternetAddress address;
|
||||
|
||||
// Native port for socket services.
|
||||
static SendPort socketService;
|
||||
|
||||
static Future<_NativeSocket> connect(String host, int port) {
|
||||
var completer = new Completer();
|
||||
static Future<List<InternetAddress>> lookup(
|
||||
String host, {InternetAddressType type: InternetAddressType.ANY}) {
|
||||
ensureSocketService();
|
||||
socketService.call([HOST_NAME_LOOKUP, host]).then((response) {
|
||||
if (isErrorResponse(response)) {
|
||||
completer.completeError(
|
||||
createError(response, "Failed host name lookup"));
|
||||
} else {
|
||||
var socket = new _NativeSocket.normal();
|
||||
socket.localHost = host;
|
||||
var result = socket.nativeCreateConnect(response, port);
|
||||
if (result is OSError) {
|
||||
completer.completeError(createError(result, "Connection failed"));
|
||||
} else {
|
||||
// Setup handlers for receiving the first write event which
|
||||
// indicate that the socket is fully connected.
|
||||
socket.setHandlers(
|
||||
write: () {
|
||||
socket.setListening(read: false, write: false);
|
||||
completer.complete(socket);
|
||||
},
|
||||
error: (e) {
|
||||
socket.close();
|
||||
completer.completeError(createError(e, "Connection failed"));
|
||||
}
|
||||
);
|
||||
socket.setListening(read: false, write: true);
|
||||
}
|
||||
}
|
||||
});
|
||||
return completer.future;
|
||||
return socketService.call([HOST_NAME_LOOKUP, host, type._value])
|
||||
.then((response) {
|
||||
if (isErrorResponse(response)) {
|
||||
throw createError(response, "Failed host name lookup");
|
||||
} else {
|
||||
return response.skip(1).map((result) {
|
||||
var type = new InternetAddressType._from(result[0]);
|
||||
return new _InternetAddress(type, result[1], host, result[2]);
|
||||
}).toList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Future<_NativeSocket> connect(host, int port) {
|
||||
return new Future.value(host)
|
||||
.then((host) {
|
||||
if (host is _InternetAddress) return host;
|
||||
return lookup(host)
|
||||
.then((list) {
|
||||
if (list.length == 0) {
|
||||
throw createError(response, "Failed host name lookup");
|
||||
}
|
||||
return list[0];
|
||||
});
|
||||
})
|
||||
.then((address) {
|
||||
ensureSocketService();
|
||||
var socket = new _NativeSocket.normal();
|
||||
socket.address = address;
|
||||
var result = socket.nativeCreateConnect(
|
||||
address._sockaddr_storage, port);
|
||||
if (result is OSError) {
|
||||
throw createError(result, "Connection failed");
|
||||
} else {
|
||||
var completer = new Completer();
|
||||
// Setup handlers for receiving the first write event which
|
||||
// indicate that the socket is fully connected.
|
||||
socket.setHandlers(
|
||||
write: () {
|
||||
socket.setListening(read: false, write: false);
|
||||
completer.complete(socket);
|
||||
},
|
||||
error: (e) {
|
||||
socket.close();
|
||||
completer.completeError(createError(e, "Connection failed"));
|
||||
}
|
||||
);
|
||||
socket.setListening(read: false, write: true);
|
||||
return completer.future;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Future<_NativeSocket> bind(String address,
|
||||
int port,
|
||||
int backlog) {
|
||||
var socket = new _NativeSocket.listen();
|
||||
socket.localHost = address;
|
||||
var result = socket.nativeCreateBindListen(address, port, backlog);
|
||||
if (result is OSError) {
|
||||
return new Future.error(
|
||||
new SocketIOException("Failed to create server socket", result));
|
||||
}
|
||||
if (port != 0) socket.localPort = port;
|
||||
return new Future.value(socket);
|
||||
return lookup(address)
|
||||
.then((list) {
|
||||
if (list.length == 0) {
|
||||
throw createError(response, "Failed host name lookup");
|
||||
}
|
||||
return list[0];
|
||||
})
|
||||
.then((address) {
|
||||
var socket = new _NativeSocket.listen();
|
||||
socket.address = address;
|
||||
var result = socket.nativeCreateBindListen(address._sockaddr_storage,
|
||||
port,
|
||||
backlog);
|
||||
if (result is OSError) {
|
||||
throw new SocketIOException(
|
||||
"Failed to create server socket", result);
|
||||
}
|
||||
if (port != 0) socket.localPort = port;
|
||||
return socket;
|
||||
});
|
||||
}
|
||||
|
||||
_NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET {
|
||||
|
@ -194,6 +252,8 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
|||
_NativeSocket accept() {
|
||||
var socket = new _NativeSocket.normal();
|
||||
if (nativeAccept(socket) != true) return null;
|
||||
socket.localPort = localPort;
|
||||
socket.address = address;
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
@ -206,8 +266,6 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
|||
return nativeGetRemotePeer()[1];
|
||||
}
|
||||
|
||||
String get host => localHost;
|
||||
|
||||
String get remoteHost {
|
||||
return nativeGetRemotePeer()[0];
|
||||
}
|
||||
|
@ -409,8 +467,9 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
|||
nativeRead(int len) native "Socket_Read";
|
||||
nativeWrite(List<int> buffer, int offset, int bytes)
|
||||
native "Socket_WriteList";
|
||||
nativeCreateConnect(String host, int port) native "Socket_CreateConnect";
|
||||
nativeCreateBindListen(String address, int port, int backlog)
|
||||
nativeCreateConnect(List<int> addr,
|
||||
int port) native "Socket_CreateConnect";
|
||||
nativeCreateBindListen(List<int> addr, int port, int backlog)
|
||||
native "ServerSocket_CreateBindListen";
|
||||
nativeAccept(_NativeSocket socket) native "ServerSocket_Accept";
|
||||
int nativeGetPort() native "Socket_GetPort";
|
||||
|
@ -503,7 +562,7 @@ class _RawSocket extends Stream<RawSocketEvent>
|
|||
bool _readEventsEnabled = true;
|
||||
bool _writeEventsEnabled = true;
|
||||
|
||||
static Future<RawSocket> connect(String host, int port) {
|
||||
static Future<RawSocket> connect(host, int port) {
|
||||
return _NativeSocket.connect(host, port)
|
||||
.then((socket) => new _RawSocket(socket));
|
||||
}
|
||||
|
@ -571,7 +630,7 @@ class _RawSocket extends Stream<RawSocketEvent>
|
|||
|
||||
int get remotePort => _socket.remotePort;
|
||||
|
||||
String get host => _socket.host;
|
||||
InternetAddress get address => _socket.address;
|
||||
|
||||
String get remoteHost => _socket.remoteHost;
|
||||
|
||||
|
@ -659,7 +718,7 @@ class _ServerSocket extends Stream<Socket>
|
|||
|
||||
|
||||
patch class Socket {
|
||||
/* patch */ static Future<Socket> connect(String host, int port) {
|
||||
/* patch */ static Future<Socket> connect(host, int port) {
|
||||
return RawSocket.connect(host, port).then(
|
||||
(socket) => new _Socket(socket));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,40 @@
|
|||
#include "bin/log.h"
|
||||
#include "bin/socket.h"
|
||||
|
||||
#define SOCKADDR_STORAGE_SET_PORT(addr, port) \
|
||||
if (addr.ss_family == AF_INET) { \
|
||||
reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port = htons(port); \
|
||||
} else { \
|
||||
reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port = htons(port); \
|
||||
}
|
||||
|
||||
#define SOCKADDR_STORAGE_GET_PORT(addr) \
|
||||
addr.ss_family == AF_INET ? \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in*>(&addr)->sin_port) : \
|
||||
ntohs(reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_port)
|
||||
|
||||
SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
|
||||
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
|
||||
sockaddr_storage *sockaddr =
|
||||
reinterpret_cast<sockaddr_storage *>(addrinfo->ai_addr);
|
||||
|
||||
// Clear the port before calling WSAAddressToString as WSAAddressToString
|
||||
// includes the port in the formatted string.
|
||||
DWORD len = INET6_ADDRSTRLEN;
|
||||
int err = WSAAddressToStringA(reinterpret_cast<LPSOCKADDR>(sockaddr),
|
||||
sizeof(sockaddr_storage),
|
||||
NULL,
|
||||
as_string_,
|
||||
&len);
|
||||
|
||||
if (err != 0) {
|
||||
as_string_[0] = 0;
|
||||
}
|
||||
memmove(reinterpret_cast<void *>(&addr_),
|
||||
addrinfo->ai_addr,
|
||||
addrinfo->ai_addrlen);
|
||||
}
|
||||
|
||||
bool Socket::Initialize() {
|
||||
static bool socket_initialized = false;
|
||||
if (socket_initialized) return true;
|
||||
|
@ -47,34 +81,34 @@ intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
|
|||
intptr_t Socket::GetPort(intptr_t fd) {
|
||||
ASSERT(reinterpret_cast<Handle*>(fd)->is_socket());
|
||||
SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
|
||||
struct sockaddr_in socket_address;
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
if (getsockname(socket_handle->socket(),
|
||||
reinterpret_cast<struct sockaddr *>(&socket_address),
|
||||
&size)) {
|
||||
Log::PrintErr("Error getsockname: %s\n", strerror(errno));
|
||||
&size) == SOCKET_ERROR) {
|
||||
Log::PrintErr("Error getsockname: %d\n", WSAGetLastError());
|
||||
return 0;
|
||||
}
|
||||
return ntohs(socket_address.sin_port);
|
||||
return SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
||||
ASSERT(reinterpret_cast<Handle*>(fd)->is_socket());
|
||||
SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
|
||||
struct sockaddr_in socket_address;
|
||||
socklen_t size = sizeof(socket_address);
|
||||
struct sockaddr_storage socket_address;
|
||||
socklen_t size = sizeof(sockaddr_storage);
|
||||
if (getpeername(socket_handle->socket(),
|
||||
reinterpret_cast<struct sockaddr *>(&socket_address),
|
||||
&size)) {
|
||||
Log::PrintErr("Error getpeername: %s\n", strerror(errno));
|
||||
Log::PrintErr("Error getpeername: %d\n", WSAGetLastError());
|
||||
return false;
|
||||
}
|
||||
*port = ntohs(socket_address.sin_port);
|
||||
*port = SOCKADDR_STORAGE_GET_PORT(socket_address);
|
||||
// Clear the port before calling WSAAddressToString as WSAAddressToString
|
||||
// includes the port in the formatted string.
|
||||
socket_address.sin_port = 0;
|
||||
DWORD len = INET_ADDRSTRLEN;
|
||||
SOCKADDR_STORAGE_SET_PORT(socket_address, 0);
|
||||
DWORD len = INET6_ADDRSTRLEN;
|
||||
int err = WSAAddressToStringA(reinterpret_cast<LPSOCKADDR>(&socket_address),
|
||||
sizeof(socket_address),
|
||||
NULL,
|
||||
|
@ -87,8 +121,8 @@ bool Socket::GetRemotePeer(intptr_t fd, char *host, intptr_t *port) {
|
|||
return true;
|
||||
}
|
||||
|
||||
intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
||||
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
intptr_t Socket::CreateConnect(sockaddr_storage addr, const intptr_t port) {
|
||||
SOCKET s = socket(addr.ss_family, SOCK_STREAM, 0);
|
||||
if (s == INVALID_SOCKET) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -105,29 +139,11 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
|
|||
FATAL("Failed setting SO_LINGER on socket");
|
||||
}
|
||||
|
||||
// Perform a name lookup for an IPv4 address.
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
struct addrinfo* result = NULL;
|
||||
status = getaddrinfo(host, 0, &hints, &result);
|
||||
if (status != NO_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copy IPv4 address and set the port.
|
||||
struct sockaddr_in server_address;
|
||||
memcpy(&server_address,
|
||||
reinterpret_cast<sockaddr_in *>(result->ai_addr),
|
||||
sizeof(server_address));
|
||||
server_address.sin_port = htons(port);
|
||||
freeaddrinfo(result); // Free data allocated by getaddrinfo.
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
status = connect(
|
||||
s,
|
||||
reinterpret_cast<struct sockaddr*>(&server_address),
|
||||
sizeof(server_address));
|
||||
reinterpret_cast<struct sockaddr*>(&addr),
|
||||
SocketAddress::GetAddrLength(addr));
|
||||
if (status == SOCKET_ERROR) {
|
||||
DWORD rc = WSAGetLastError();
|
||||
closesocket(s);
|
||||
|
@ -192,13 +208,17 @@ intptr_t ServerSocket::Accept(intptr_t fd) {
|
|||
}
|
||||
|
||||
|
||||
const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
||||
// Perform a name lookup for an IPv4 address.
|
||||
SocketAddresses* Socket::LookupAddress(const char* host,
|
||||
int type,
|
||||
OSError** os_error) {
|
||||
Initialize();
|
||||
|
||||
// Perform a name lookup for a host name.
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_family = SocketAddress::FromType(type);
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = 0;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
struct addrinfo* info = NULL;
|
||||
int status = getaddrinfo(host, 0, &hints, &info);
|
||||
|
@ -209,35 +229,27 @@ const char* Socket::LookupIPv4Address(char* host, OSError** os_error) {
|
|||
*os_error = new OSError();
|
||||
return NULL;
|
||||
}
|
||||
// Convert the address into IPv4 dotted decimal notation.
|
||||
char* buffer = reinterpret_cast<char*>(malloc(INET_ADDRSTRLEN));
|
||||
sockaddr_in *sockaddr = reinterpret_cast<sockaddr_in *>(info->ai_addr);
|
||||
|
||||
// Clear the port before calling WSAAddressToString as WSAAddressToString
|
||||
// includes the port in the formatted string.
|
||||
DWORD len = INET_ADDRSTRLEN;
|
||||
int err = WSAAddressToStringA(reinterpret_cast<LPSOCKADDR>(sockaddr),
|
||||
sizeof(sockaddr_in),
|
||||
NULL,
|
||||
buffer,
|
||||
&len);
|
||||
if (err != 0) {
|
||||
free(buffer);
|
||||
return NULL;
|
||||
intptr_t count = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
|
||||
}
|
||||
return buffer;
|
||||
SocketAddresses* addresses = new SocketAddresses(count);
|
||||
intptr_t i = 0;
|
||||
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
|
||||
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
|
||||
addresses->SetAt(i, new SocketAddress(c));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(info);
|
||||
return addresses;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ServerSocket::CreateBindListen(const char* host,
|
||||
intptr_t ServerSocket::CreateBindListen(sockaddr_storage addr,
|
||||
intptr_t port,
|
||||
intptr_t backlog) {
|
||||
unsigned long socket_addr = inet_addr(host); // NOLINT
|
||||
if (socket_addr == INADDR_NONE) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
SOCKET s = socket(addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (s == INVALID_SOCKET) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -255,14 +267,19 @@ intptr_t ServerSocket::CreateBindListen(const char* host,
|
|||
return -1;
|
||||
}
|
||||
|
||||
sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = socket_addr;
|
||||
addr.sin_port = htons(port);
|
||||
if (addr.ss_family == AF_INET6) {
|
||||
optval = false;
|
||||
setsockopt(s,
|
||||
IPPROTO_IPV6,
|
||||
IPV6_V6ONLY,
|
||||
reinterpret_cast<const char*>(&optval),
|
||||
sizeof(optval));
|
||||
}
|
||||
|
||||
SOCKADDR_STORAGE_SET_PORT(addr, port);
|
||||
status = bind(s,
|
||||
reinterpret_cast<struct sockaddr *>(&addr),
|
||||
sizeof(addr));
|
||||
SocketAddress::GetAddrLength(addr));
|
||||
if (status == SOCKET_ERROR) {
|
||||
DWORD rc = WSAGetLastError();
|
||||
closesocket(s);
|
||||
|
|
|
@ -55,15 +55,15 @@ void VmStats::StartServer(int port, const char* root_dir) {
|
|||
// TODO(tball): allow host to be specified.
|
||||
char* host = const_cast<char*>(DEFAULT_HOST);
|
||||
OSError* os_error;
|
||||
const char* host_ip = Socket::LookupIPv4Address(host, &os_error);
|
||||
if (host_ip == NULL) {
|
||||
SocketAddresses* addresses = Socket::LookupAddress(host, -1, &os_error);
|
||||
if (addresses == NULL) {
|
||||
Log::PrintErr("Failed IP lookup of VmStats host %s: %s\n",
|
||||
host, os_error->message());
|
||||
return;
|
||||
}
|
||||
|
||||
const intptr_t BACKLOG = 128; // Default value from HttpServer.dart
|
||||
int64_t address = ServerSocket::CreateBindListen(host_ip, port, BACKLOG);
|
||||
int64_t address = ServerSocket::CreateBindListen(
|
||||
addresses->GetAt(0)->addr(), port, BACKLOG);
|
||||
if (address < 0) {
|
||||
Log::PrintErr("Failed binding VmStats socket: %s:%d\n", host, port);
|
||||
return;
|
||||
|
|
|
@ -1838,7 +1838,7 @@ class _DetachedSocket extends Stream<List<int>> implements Socket {
|
|||
|
||||
int get port => _socket.port;
|
||||
|
||||
String get host => _socket.host;
|
||||
InternetAddress get address => _socket.address;
|
||||
|
||||
String get remoteHost => _socket.remoteHost;
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ abstract class SecureSocket implements Socket {
|
|||
* to continue the [SecureSocket] connection.
|
||||
*/
|
||||
static Future<SecureSocket> connect(
|
||||
String host,
|
||||
host,
|
||||
int port,
|
||||
{bool sendClientCertificate: false,
|
||||
String certificateName,
|
||||
|
@ -208,7 +208,7 @@ abstract class RawSecureSocket implements RawSocket {
|
|||
* to continue the [RawSecureSocket] connection.
|
||||
*/
|
||||
static Future<RawSecureSocket> connect(
|
||||
String host,
|
||||
host,
|
||||
int port,
|
||||
{bool sendClientCertificate: false,
|
||||
String certificateName,
|
||||
|
@ -244,7 +244,7 @@ abstract class RawSecureSocket implements RawSocket {
|
|||
String certificateName,
|
||||
bool onBadCertificate(X509Certificate certificate)}) {
|
||||
return _RawSecureSocket.connect(
|
||||
socket.host,
|
||||
socket.address,
|
||||
socket.port,
|
||||
certificateName,
|
||||
is_server: false,
|
||||
|
@ -345,7 +345,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
|||
StreamSubscription<RawSocketEvent> _socketSubscription;
|
||||
List<int> _carryOverData;
|
||||
int _carryOverDataIndex = 0;
|
||||
final String host;
|
||||
final InternetAddress address;
|
||||
final bool is_server;
|
||||
final String certificateName;
|
||||
final bool requestClientCertificate;
|
||||
|
@ -366,7 +366,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
|||
_SecureFilter _secureFilter = new _SecureFilter();
|
||||
|
||||
static Future<_RawSecureSocket> connect(
|
||||
String host,
|
||||
host,
|
||||
int requestedPort,
|
||||
String certificateName,
|
||||
{bool is_server,
|
||||
|
@ -376,8 +376,15 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
|||
bool requestClientCertificate: false,
|
||||
bool requireClientCertificate: false,
|
||||
bool sendClientCertificate: false,
|
||||
bool onBadCertificate(X509Certificate certificate)}){
|
||||
return new _RawSecureSocket(host,
|
||||
bool onBadCertificate(X509Certificate certificate)}) {
|
||||
var future;
|
||||
if (host is String) {
|
||||
future = InternetAddress.lookup(host).then((addrs) => addrs.first);
|
||||
} else {
|
||||
future = new Future.value(host);
|
||||
}
|
||||
return future.then((addr) {
|
||||
return new _RawSecureSocket(addr,
|
||||
requestedPort,
|
||||
certificateName,
|
||||
is_server,
|
||||
|
@ -389,10 +396,11 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
|||
sendClientCertificate,
|
||||
onBadCertificate)
|
||||
._handshakeComplete.future;
|
||||
});
|
||||
}
|
||||
|
||||
_RawSecureSocket(
|
||||
String this.host,
|
||||
InternetAddress this.address,
|
||||
int requestedPort,
|
||||
String this.certificateName,
|
||||
bool this.is_server,
|
||||
|
@ -421,7 +429,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
|||
}
|
||||
var futureSocket;
|
||||
if (socket == null) {
|
||||
futureSocket = RawSocket.connect(host, requestedPort);
|
||||
futureSocket = RawSocket.connect(address, requestedPort);
|
||||
} else {
|
||||
futureSocket = new Future.value(socket);
|
||||
}
|
||||
|
@ -441,7 +449,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
|||
_socketSubscription.onDone(_doneHandler);
|
||||
}
|
||||
_connectPending = true;
|
||||
_secureFilter.connect(host,
|
||||
_secureFilter.connect(rawSocket.address.host,
|
||||
port,
|
||||
is_server,
|
||||
certificateName,
|
||||
|
@ -475,9 +483,9 @@ class _RawSecureSocket extends Stream<RawSocketEvent>
|
|||
void _verifyFields() {
|
||||
assert(is_server is bool);
|
||||
assert(_socket == null || _socket is RawSocket);
|
||||
if (host is! String) {
|
||||
if (address is! InternetAddress) {
|
||||
throw new ArgumentError(
|
||||
"RawSecureSocket constructor: host is not a String");
|
||||
"RawSecureSocket constructor: host is not an InternetAddress");
|
||||
}
|
||||
if (certificateName != null && certificateName is! String) {
|
||||
throw new ArgumentError("certificateName is not null or a String");
|
||||
|
|
|
@ -4,6 +4,73 @@
|
|||
|
||||
part of dart.io;
|
||||
|
||||
|
||||
/**
|
||||
* [InternetAddressType] is the type an [InternetAddress]. Currently, IPv4 and
|
||||
* IPv6 are supported.
|
||||
*/
|
||||
class InternetAddressType {
|
||||
static const InternetAddressType IPv4 = const InternetAddressType._(0);
|
||||
static const InternetAddressType IPv6 = const InternetAddressType._(1);
|
||||
static const InternetAddressType ANY = const InternetAddressType._(-1);
|
||||
|
||||
final int _value;
|
||||
|
||||
const InternetAddressType._(int this._value);
|
||||
|
||||
factory InternetAddressType._from(int value) {
|
||||
if (value == 0) return IPv4;
|
||||
if (value == 1) return IPv6;
|
||||
throw new ArgumentError("Invalid type: $value");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the type, e.g. "IPv4" or "IPv6".
|
||||
*/
|
||||
String get name {
|
||||
switch (_value) {
|
||||
case -1: return "ANY";
|
||||
case 0: return "IPv4";
|
||||
case 1: return "IPv6";
|
||||
default: throw new ArgumentError("Invalid InternetAddress");
|
||||
}
|
||||
}
|
||||
|
||||
String toString() => "InternetAddressType($name)";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The [InternetAddress] is an object reflecting either a remote or a local
|
||||
* address, for wich a socket can be connected to or bound on.
|
||||
*
|
||||
*/
|
||||
abstract class InternetAddress {
|
||||
/**
|
||||
* The [type] of the [InternetAddress] specified what IP procotol.
|
||||
*/
|
||||
InternetAddressType type;
|
||||
|
||||
/**
|
||||
* The resolved address of the host.
|
||||
*/
|
||||
String get address;
|
||||
|
||||
/**
|
||||
* The host used to lookup the address.
|
||||
*/
|
||||
String get host;
|
||||
|
||||
/**
|
||||
* Lookup a host, returning a Future of a list of [InternetAddress]s. If
|
||||
* [type] is [InternetAddressType.ANY], it will lookup both IPv4 and IPv6
|
||||
* addresses. The order of the list depends on the local machine and the DNS
|
||||
* lookup performed, and can as such change over time.
|
||||
*/
|
||||
external static Future<List<InternetAddress>> lookup(
|
||||
String host, {InternetAddressType type: InternetAddressType.ANY});
|
||||
}
|
||||
|
||||
/**
|
||||
* The RawServerSocket is a server socket, providing a stream of low-level
|
||||
* [RawSocket]s.
|
||||
|
@ -32,8 +99,8 @@ abstract class RawServerSocket implements Stream<RawSocket> {
|
|||
* the system.
|
||||
*/
|
||||
external static Future<RawServerSocket> bind([String address = "127.0.0.1",
|
||||
int port = 0,
|
||||
int backlog = 0]);
|
||||
int port = 0,
|
||||
int backlog = 0]);
|
||||
|
||||
/**
|
||||
* Returns the port used by this socket.
|
||||
|
@ -144,8 +211,12 @@ abstract class RawSocket implements Stream<RawSocketEvent> {
|
|||
* Creates a new socket connection to the host and port and returns a [Future]
|
||||
* that will complete with either a [RawSocket] once connected or an error
|
||||
* if the host-lookup or connection failed.
|
||||
*
|
||||
* [host] can either be a [String] or an [InternetAddress]. If [host] is a
|
||||
* [String], [connect] will perform a [InternetAddress.lookup] and use
|
||||
* the first value in the list.
|
||||
*/
|
||||
external static Future<RawSocket> connect(String host, int port);
|
||||
external static Future<RawSocket> connect(host, int port);
|
||||
|
||||
/**
|
||||
* Returns the number of received and non-read bytes in the socket that
|
||||
|
@ -181,9 +252,9 @@ abstract class RawSocket implements Stream<RawSocketEvent> {
|
|||
int get remotePort;
|
||||
|
||||
/**
|
||||
* Returns the host used to connect this socket.
|
||||
* Returns the [InternetAddress] used to connect this socket.
|
||||
*/
|
||||
String get host;
|
||||
InternetAddress get address;
|
||||
|
||||
/**
|
||||
* Returns the remote host connected to by this socket.
|
||||
|
@ -238,8 +309,12 @@ abstract class Socket implements Stream<List<int>>, IOSink {
|
|||
* Creats a new socket connection to the host and port and returns a [Future]
|
||||
* that will complete with either a [Socket] once connected or an error
|
||||
* if the host-lookup or connection failed.
|
||||
*
|
||||
* [host] can either be a [String] or an [InternetAddress]. If [host] is a
|
||||
* [String], [connect] will perform a [InternetAddress.lookup] and use
|
||||
* the first value in the list.
|
||||
*/
|
||||
external static Future<Socket> connect(String host, int port);
|
||||
external static Future<Socket> connect(host, int port);
|
||||
|
||||
/**
|
||||
* Destroy the socket in both directions. Calling [destroy] will make the
|
||||
|
@ -270,9 +345,9 @@ abstract class Socket implements Stream<List<int>>, IOSink {
|
|||
int get remotePort;
|
||||
|
||||
/**
|
||||
* Returns the host used to connect this socket.
|
||||
* Returns the [InternetAddress] used to connect this socket.
|
||||
*/
|
||||
String get host;
|
||||
InternetAddress get address;
|
||||
|
||||
/**
|
||||
* Returns the remote host connected to by this socket.
|
||||
|
|
|
@ -30,7 +30,7 @@ void testClientAndServerCloseNoListen(int connections) {
|
|||
});
|
||||
var client = new HttpClient();
|
||||
for (int i = 0; i < connections; i++) {
|
||||
client.get("localhost", server.port, "/")
|
||||
client.get("127.0.0.1", server.port, "/")
|
||||
.then((request) => request.close())
|
||||
.then((response) {
|
||||
});
|
||||
|
@ -61,7 +61,7 @@ void testClientCloseServerListen(int connections) {
|
|||
});
|
||||
var client = new HttpClient();
|
||||
for (int i = 0; i < connections; i++) {
|
||||
client.get("localhost", server.port, "/")
|
||||
client.get("127.0.0.1", server.port, "/")
|
||||
.then((request) => request.close())
|
||||
.then((response) => check());
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ void testClientCloseSendingResponse(int connections) {
|
|||
});
|
||||
var client = new HttpClient();
|
||||
for (int i = 0; i < connections; i++) {
|
||||
client.get("localhost", server.port, "/")
|
||||
client.get("127.0.0.1", server.port, "/")
|
||||
.then((request) => request.close())
|
||||
.then((response) {
|
||||
// Ensure we don't accept the response until we have send the entire
|
||||
|
|
|
@ -19,7 +19,7 @@ void testServerCompress() {
|
|||
request.response.close();
|
||||
});
|
||||
var client = new HttpClient();
|
||||
client.get("localhost", server.port, "/")
|
||||
client.get("127.0.0.1", server.port, "/")
|
||||
.then((request) {
|
||||
request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip,deflate");
|
||||
return request.close();
|
||||
|
@ -55,7 +55,7 @@ void testAcceptEncodingHeader() {
|
|||
request.response.close();
|
||||
});
|
||||
var client = new HttpClient();
|
||||
client.get("localhost", server.port, "/")
|
||||
client.get("127.0.0.1", server.port, "/")
|
||||
.then((request) {
|
||||
request.headers.set(HttpHeaders.ACCEPT_ENCODING, encoding);
|
||||
return request.close();
|
||||
|
|
|
@ -12,7 +12,7 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
|
||||
Future getData(HttpClient client, int port, bool chunked, int length) {
|
||||
return client.get("localhost", port, "/?chunked=$chunked&length=$length")
|
||||
return client.get("127.0.0.1", port, "/?chunked=$chunked&length=$length")
|
||||
.then((request) => request.close())
|
||||
.then((response) {
|
||||
return response.fold(0, (bytes, data) => bytes + data.length)
|
||||
|
|
|
@ -22,8 +22,8 @@ class Server {
|
|||
var x = new Completer();
|
||||
Future f = secure
|
||||
? HttpServer.bindSecure(
|
||||
"127.0.0.1", 0, certificateName: 'localhost_cert')
|
||||
: HttpServer.bind();
|
||||
"localhost", 0, certificateName: 'localhost_cert')
|
||||
: HttpServer.bind("localhost");
|
||||
return f.then((s) {
|
||||
server = s;
|
||||
x.complete(this);
|
||||
|
@ -97,7 +97,7 @@ class ProxyServer {
|
|||
|
||||
Future<ProxyServer> start() {
|
||||
var x = new Completer();
|
||||
HttpServer.bind().then((s) {
|
||||
HttpServer.bind("localhost").then((s) {
|
||||
server = s;
|
||||
x.complete(this);
|
||||
server.listen((HttpRequest request) {
|
||||
|
@ -196,7 +196,7 @@ void testDirectProxy() {
|
|||
};
|
||||
|
||||
for (int i = 0; i < proxy.length; i++) {
|
||||
client.getUrl(Uri.parse("http://127.0.0.1:${server.port}/$i"))
|
||||
client.getUrl(Uri.parse("http://localhost:${server.port}/$i"))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
String content = "$i$i$i";
|
||||
clientRequest.contentLength = content.length;
|
||||
|
@ -254,7 +254,7 @@ void testProxy() {
|
|||
test(bool secure) {
|
||||
String url = secure
|
||||
? "https://localhost:${secureServer.port}/$i"
|
||||
: "http://127.0.0.1:${server.port}/$i";
|
||||
: "http://localhost:${server.port}/$i";
|
||||
|
||||
client.postUrl(Uri.parse(url))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
|
@ -290,7 +290,7 @@ void testProxyChain() {
|
|||
// Setup two proxy servers having the first using the second as its proxy.
|
||||
setupProxyServer().then((proxyServer1) {
|
||||
setupProxyServer().then((proxyServer2) {
|
||||
proxyServer1.client.findProxy = (_) => "PROXY 127.0.0.1:${proxyServer2.port}";
|
||||
proxyServer1.client.findProxy = (_) => "PROXY localhost:${proxyServer2.port}";
|
||||
|
||||
setupServer(2, directRequestPaths: ["/4"]).then((server) {
|
||||
HttpClient client = new HttpClient();
|
||||
|
@ -322,7 +322,7 @@ void testProxyChain() {
|
|||
};
|
||||
|
||||
for (int i = 0; i < proxy.length; i++) {
|
||||
client.getUrl(Uri.parse("http://127.0.0.1:${server.port}/$i"))
|
||||
client.getUrl(Uri.parse("http://localhost:${server.port}/$i"))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
String content = "$i$i$i";
|
||||
clientRequest.contentLength = content.length;
|
||||
|
@ -366,7 +366,7 @@ void testProxyFromEnviroment() {
|
|||
test(bool secure) {
|
||||
String url = secure
|
||||
? "https://localhost:${secureServer.port}/$i"
|
||||
: "http://127.0.0.1:${server.port}/$i";
|
||||
: "http://localhost:${server.port}/$i";
|
||||
|
||||
client.postUrl(Uri.parse(url))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
|
@ -420,7 +420,7 @@ void testProxyAuthenticate() {
|
|||
test(bool secure) {
|
||||
String url = secure
|
||||
? "https://localhost:${secureServer.port}/$i"
|
||||
: "http://127.0.0.1:${server.port}/$i";
|
||||
: "http://localhost:${server.port}/$i";
|
||||
|
||||
client.postUrl(Uri.parse(url))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
|
@ -456,7 +456,7 @@ void testProxyAuthenticate() {
|
|||
test(bool secure) {
|
||||
String url = secure
|
||||
? "https://localhost:${secureServer.port}/$i"
|
||||
: "http://127.0.0.1:${server.port}/$i";
|
||||
: "http://localhost:${server.port}/$i";
|
||||
|
||||
client.postUrl(Uri.parse(url))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
|
@ -501,7 +501,7 @@ void testProxyAuthenticate() {
|
|||
test(bool secure) {
|
||||
String url = secure
|
||||
? "https://localhost:${secureServer.port}/A"
|
||||
: "http://127.0.0.1:${server.port}/A";
|
||||
: "http://localhost:${server.port}/A";
|
||||
|
||||
client.postUrl(Uri.parse(url))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
|
@ -556,7 +556,7 @@ void testRealProxy() {
|
|||
};
|
||||
|
||||
for (int i = 0; i < proxy.length; i++) {
|
||||
client.getUrl(Uri.parse("http://127.0.0.1:${server.port}/$i"))
|
||||
client.getUrl(Uri.parse("http://localhost:${server.port}/$i"))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
String content = "$i$i$i";
|
||||
clientRequest.contentLength = content.length;
|
||||
|
@ -594,7 +594,7 @@ void testRealProxyAuth() {
|
|||
};
|
||||
|
||||
for (int i = 0; i < proxy.length; i++) {
|
||||
client.getUrl(Uri.parse("http://127.0.0.1:${server.port}/$i"))
|
||||
client.getUrl(Uri.parse("http://localhost:${server.port}/$i"))
|
||||
.then((HttpClientRequest clientRequest) {
|
||||
String content = "$i$i$i";
|
||||
clientRequest.contentLength = content.length;
|
||||
|
|
|
@ -146,7 +146,7 @@ void testEarlyClose3() {
|
|||
server.close();
|
||||
});
|
||||
});
|
||||
Socket.connect("localhost", server.port)
|
||||
Socket.connect("127.0.0.1", server.port)
|
||||
.then((socket) {
|
||||
socket.write("GET / HTTP/1.1\r\n");
|
||||
socket.write("Content-Length: 10\r\n");
|
||||
|
|
|
@ -8,13 +8,12 @@ import "dart:io";
|
|||
import "dart:uri";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
|
||||
|
||||
Function test() {
|
||||
var keepAlive = new ReceivePort();
|
||||
HttpServer.bindSecure(SERVER_ADDRESS,
|
||||
HttpServer.bindSecure(HOST_NAME,
|
||||
0,
|
||||
backlog: 5,
|
||||
certificateName: 'localhost_cert',
|
||||
|
|
|
@ -19,11 +19,6 @@ void testBadHostName() {
|
|||
});
|
||||
}
|
||||
|
||||
void InitializeSSL() {
|
||||
SecureSocket.initialize();
|
||||
}
|
||||
|
||||
void main() {
|
||||
testBadHostName();
|
||||
Expect.throws(InitializeSSL);
|
||||
}
|
||||
|
|
|
@ -8,12 +8,11 @@ import "dart:io";
|
|||
import "dart:uri";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
|
||||
void testListenOn() {
|
||||
void test(void onDone()) {
|
||||
HttpServer.bindSecure(SERVER_ADDRESS,
|
||||
HttpServer.bindSecure(HOST_NAME,
|
||||
0,
|
||||
backlog: 5,
|
||||
certificateName: 'localhost_cert').then((server) {
|
||||
|
|
|
@ -12,7 +12,6 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
|
||||
|
@ -25,7 +24,7 @@ void testCloseOneEnd(String toClose) {
|
|||
.then((_) {
|
||||
port.close();
|
||||
});
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((server) {
|
||||
server.listen((serverConnection) {
|
||||
serverConnection.listen((event) {
|
||||
if (toClose == "server" || event == RawSocketEvent.READ_CLOSED) {
|
||||
|
@ -55,7 +54,7 @@ void testCloseOneEnd(String toClose) {
|
|||
|
||||
void testCloseBothEnds() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((server) {
|
||||
var clientEndFuture = RawSecureSocket.connect(HOST_NAME, server.port);
|
||||
server.listen((serverEnd) {
|
||||
clientEndFuture.then((clientEnd) {
|
||||
|
@ -75,7 +74,7 @@ testPauseServerSocket() {
|
|||
|
||||
ReceivePort port = new ReceivePort();
|
||||
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS,
|
||||
RawSecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
2 * socketCount,
|
||||
CERTIFICATE).then((server) {
|
||||
|
@ -117,7 +116,7 @@ testCloseServer() {
|
|||
ReceivePort port = new ReceivePort();
|
||||
List ends = [];
|
||||
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 15, CERTIFICATE).then((server) {
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 15, CERTIFICATE).then((server) {
|
||||
Expect.isTrue(server.port > 0);
|
||||
void checkDone() {
|
||||
if (ends.length < 2 * socketCount) return;
|
||||
|
|
|
@ -12,22 +12,21 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
|
||||
void testArguments() {
|
||||
Expect.throws(() =>
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 65536, 5, CERTIFICATE));
|
||||
RawSecureServerSocket.bind(HOST_NAME, 65536, 5, CERTIFICATE));
|
||||
Expect.throws(() =>
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, -1, CERTIFICATE));
|
||||
RawSecureServerSocket.bind(HOST_NAME, -1, CERTIFICATE));
|
||||
Expect.throws(() =>
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, -1, CERTIFICATE));
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, -1, CERTIFICATE));
|
||||
}
|
||||
|
||||
void testSimpleBind() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((s) {
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((s) {
|
||||
Expect.isTrue(s.port > 0);
|
||||
s.close();
|
||||
port.close();
|
||||
|
@ -59,8 +58,8 @@ void testInvalidBind() {
|
|||
// Either an error or a successful bind is allowed.
|
||||
// Windows platforms allow multiple binding to the same socket, with
|
||||
// unpredictable results.
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((s) {
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS,
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((s) {
|
||||
RawSecureServerSocket.bind(HOST_NAME,
|
||||
s.port,
|
||||
5,
|
||||
CERTIFICATE).then((t) {
|
||||
|
@ -81,7 +80,7 @@ void testInvalidBind() {
|
|||
|
||||
void testSimpleConnect(String certificate) {
|
||||
ReceivePort port = new ReceivePort();
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, certificate).then((server) {
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 5, certificate).then((server) {
|
||||
var clientEndFuture = RawSecureSocket.connect(HOST_NAME, server.port);
|
||||
server.listen((serverEnd) {
|
||||
clientEndFuture.then((clientEnd) {
|
||||
|
@ -96,7 +95,7 @@ void testSimpleConnect(String certificate) {
|
|||
|
||||
void testSimpleConnectFail(String certificate) {
|
||||
ReceivePort port = new ReceivePort();
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, certificate).then((server) {
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 5, certificate).then((server) {
|
||||
var clientEndFuture = RawSecureSocket.connect(HOST_NAME, server.port)
|
||||
.then((clientEnd) {
|
||||
Expect.fail("No client connection expected.");
|
||||
|
@ -116,7 +115,7 @@ void testSimpleConnectFail(String certificate) {
|
|||
|
||||
void testServerListenAfterConnect() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
|
||||
RawSecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((server) {
|
||||
Expect.isTrue(server.port > 0);
|
||||
var clientEndFuture = RawSecureSocket.connect(HOST_NAME, server.port);
|
||||
new Timer(const Duration(milliseconds: 500), () {
|
||||
|
@ -441,9 +440,9 @@ void testSimpleReadWrite(bool listenSecure,
|
|||
|
||||
if (listenSecure) {
|
||||
RawSecureServerSocket.bind(
|
||||
SERVER_ADDRESS, 0, 5, CERTIFICATE).then(serverReady);
|
||||
HOST_NAME, 0, 5, CERTIFICATE).then(serverReady);
|
||||
} else {
|
||||
RawServerSocket.bind(SERVER_ADDRESS, 0, 5).then(serverReady);
|
||||
RawServerSocket.bind(HOST_NAME, 0, 5).then(serverReady);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import "dart:isolate";
|
|||
|
||||
Future<HttpServer> startServer() {
|
||||
return HttpServer.bindSecure(
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
0,
|
||||
backlog: 5,
|
||||
certificateName: 'localhost_cert').then((server) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import "dart:isolate";
|
|||
|
||||
Future<HttpServer> startServer() {
|
||||
return HttpServer.bindSecure(
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
0,
|
||||
backlog: 5,
|
||||
certificateName: 'localhost_cert').then((server) {
|
||||
|
|
|
@ -12,11 +12,10 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
Future<RawSecureServerSocket> startEchoServer() {
|
||||
return RawSecureServerSocket.bind(SERVER_ADDRESS,
|
||||
return RawSecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE).then((server) {
|
||||
|
|
|
@ -12,11 +12,10 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
Future<SecureServerSocket> startEchoServer() {
|
||||
return SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
return SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE).then((server) {
|
||||
|
|
|
@ -12,11 +12,10 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
Future<SecureServerSocket> startServer() {
|
||||
return SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
return SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE).then((server) {
|
||||
|
|
|
@ -7,13 +7,12 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
|
||||
void testClientCertificate() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE,
|
||||
|
@ -42,7 +41,7 @@ void testClientCertificate() {
|
|||
|
||||
void testRequiredClientCertificate() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE,
|
||||
|
@ -71,7 +70,7 @@ void testRequiredClientCertificate() {
|
|||
|
||||
void testNoClientCertificate() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE,
|
||||
|
@ -94,7 +93,7 @@ void testNoClientCertificate() {
|
|||
void testNoRequiredClientCertificate() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
bool clientError = false;
|
||||
SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE,
|
||||
|
|
|
@ -12,7 +12,6 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
|
||||
|
@ -25,7 +24,7 @@ void testCloseOneEnd(String toClose) {
|
|||
.then((_) {
|
||||
port.close();
|
||||
});
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((server) {
|
||||
server.listen((serverConnection) {
|
||||
serverConnection.listen(
|
||||
(data) {
|
||||
|
@ -61,7 +60,7 @@ void testCloseOneEnd(String toClose) {
|
|||
|
||||
void testCloseBothEnds() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((server) {
|
||||
var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port);
|
||||
server.listen((serverEnd) {
|
||||
clientEndFuture.then((clientEnd) {
|
||||
|
@ -81,7 +80,7 @@ testPauseServerSocket() {
|
|||
|
||||
ReceivePort port = new ReceivePort();
|
||||
|
||||
SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
2 * socketCount,
|
||||
CERTIFICATE).then((server) {
|
||||
|
@ -125,7 +124,7 @@ testCloseServer() {
|
|||
ReceivePort port = new ReceivePort();
|
||||
List ends = [];
|
||||
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 15, CERTIFICATE).then((server) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 15, CERTIFICATE).then((server) {
|
||||
Expect.isTrue(server.port > 0);
|
||||
void checkDone() {
|
||||
if (ends.length < 2 * socketCount) return;
|
||||
|
|
|
@ -12,22 +12,21 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
|
||||
void testArguments() {
|
||||
Expect.throws(() =>
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 65536, 5, CERTIFICATE));
|
||||
SecureServerSocket.bind(HOST_NAME, 65536, 5, CERTIFICATE));
|
||||
Expect.throws(() =>
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, -1, CERTIFICATE));
|
||||
SecureServerSocket.bind(HOST_NAME, -1, CERTIFICATE));
|
||||
Expect.throws(() =>
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, -1, CERTIFICATE));
|
||||
SecureServerSocket.bind(HOST_NAME, 0, -1, CERTIFICATE));
|
||||
}
|
||||
|
||||
void testSimpleBind() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((s) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((s) {
|
||||
Expect.isTrue(s.port > 0);
|
||||
s.close();
|
||||
port.close();
|
||||
|
@ -59,8 +58,8 @@ void testInvalidBind() {
|
|||
// Either an error or a successful bind is allowed.
|
||||
// Windows platforms allow multiple binding to the same socket, with
|
||||
// unpredictable results.
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((s) {
|
||||
SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((s) {
|
||||
SecureServerSocket.bind(HOST_NAME,
|
||||
s.port,
|
||||
5,
|
||||
CERTIFICATE).then((t) {
|
||||
|
@ -80,7 +79,7 @@ void testInvalidBind() {
|
|||
|
||||
void testSimpleConnect(String certificate) {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, certificate).then((server) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, certificate).then((server) {
|
||||
var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port);
|
||||
server.listen((serverEnd) {
|
||||
clientEndFuture.then((clientEnd) {
|
||||
|
@ -95,7 +94,7 @@ void testSimpleConnect(String certificate) {
|
|||
|
||||
void testSimpleConnectFail(String certificate) {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, certificate).then((server) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, certificate).then((server) {
|
||||
var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port)
|
||||
.then((clientEnd) {
|
||||
Expect.fail("No client connection expected.");
|
||||
|
@ -115,7 +114,7 @@ void testSimpleConnectFail(String certificate) {
|
|||
|
||||
void testServerListenAfterConnect() {
|
||||
ReceivePort port = new ReceivePort();
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((server) {
|
||||
Expect.isTrue(server.port > 0);
|
||||
var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port);
|
||||
new Timer(const Duration(milliseconds: 500), () {
|
||||
|
@ -156,7 +155,7 @@ void testSimpleReadWrite() {
|
|||
}
|
||||
}
|
||||
|
||||
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
|
||||
SecureServerSocket.bind(HOST_NAME, 0, 5, CERTIFICATE).then((server) {
|
||||
server.listen((client) {
|
||||
int bytesRead = 0;
|
||||
int bytesWritten = 0;
|
||||
|
|
|
@ -21,11 +21,10 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
Future<SecureServerSocket> startServer() {
|
||||
return SecureServerSocket.bind(SERVER_ADDRESS,
|
||||
return SecureServerSocket.bind(HOST_NAME,
|
||||
0,
|
||||
5,
|
||||
CERTIFICATE).then((server) {
|
||||
|
|
|
@ -31,12 +31,12 @@ void main() {
|
|||
}
|
||||
|
||||
Future testCertificateCallback({String host, bool acceptCertificate}) {
|
||||
Expect.throws(
|
||||
() {
|
||||
var x = 7;
|
||||
SecureSocket.connect(host, 443, onBadCertificate: x);
|
||||
},
|
||||
(e) => e is ArgumentError || e is TypeError);
|
||||
try {
|
||||
var x = 7;
|
||||
SecureSocket.connect(host, 443, onBadCertificate: x)
|
||||
.catchError((e) {}, test: (e) => e is ArgumentError);
|
||||
} on TypeError catch (e) {
|
||||
}
|
||||
|
||||
bool badCertificateCallback(X509Certificate certificate) {
|
||||
Expect.isTrue(certificate.subject.contains("O=Google Inc"));
|
||||
|
|
|
@ -13,7 +13,7 @@ import "dart:io";
|
|||
|
||||
Future<HttpServer> startServer() {
|
||||
return HttpServer.bindSecure(
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
0,
|
||||
backlog: 5,
|
||||
certificateName: 'localhost_cert').then((server) {
|
||||
|
|
88
tests/standalone/io/socket_ipv6_test.dart
Normal file
88
tests/standalone/io/socket_ipv6_test.dart
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
void testIPv6toIPv6() {
|
||||
ServerSocket.bind("::0").then((server) {
|
||||
server.listen((socket) {
|
||||
socket.destroy();
|
||||
server.close();
|
||||
});
|
||||
Socket.connect("::1", server.port).then((socket) {
|
||||
socket.destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void testIPv4toIPv6() {
|
||||
ServerSocket.bind("::0").then((server) {
|
||||
server.listen((socket) {
|
||||
socket.destroy();
|
||||
server.close();
|
||||
});
|
||||
Socket.connect("127.0.0.1", server.port).then((socket) {
|
||||
socket.destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void testIPv6toIPv4() {
|
||||
ServerSocket.bind("127.0.0.1").then((server) {
|
||||
server.listen((socket) {
|
||||
throw "Unexpected socket";
|
||||
});
|
||||
Socket.connect("::1", server.port).catchError((e) {
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void testIPv4toIPv4() {
|
||||
ServerSocket.bind("127.0.0.1").then((server) {
|
||||
server.listen((socket) {
|
||||
socket.destroy();
|
||||
server.close();
|
||||
});
|
||||
Socket.connect("127.0.0.1", server.port).then((socket) {
|
||||
socket.destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void testIPv6Lookup() {
|
||||
var port = new ReceivePort();
|
||||
InternetAddress.lookup("::0").then((list) {
|
||||
if (list.length < 0) throw "no address";
|
||||
for (var entry in list) {
|
||||
if (entry.type != InternetAddressType.IPv6) {
|
||||
throw "Wrong IP type";
|
||||
}
|
||||
}
|
||||
port.close();
|
||||
});
|
||||
}
|
||||
|
||||
void testIPv4Lookup() {
|
||||
var port = new ReceivePort();
|
||||
InternetAddress.lookup("127.0.0.1").then((list) {
|
||||
if (list.length < 0) throw "no addresse";
|
||||
for (var entry in list) {
|
||||
if (entry.type != InternetAddressType.IPv4) {
|
||||
throw "Wrong IP type";
|
||||
}
|
||||
}
|
||||
port.close();
|
||||
});
|
||||
}
|
||||
|
||||
void main() {
|
||||
testIPv6toIPv6();
|
||||
testIPv4toIPv6();
|
||||
testIPv6toIPv4();
|
||||
testIPv4toIPv4();
|
||||
testIPv6Lookup();
|
||||
testIPv4Lookup();
|
||||
}
|
|
@ -12,7 +12,6 @@ import "dart:async";
|
|||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
|
||||
const SERVER_ADDRESS = "127.0.0.1";
|
||||
const HOST_NAME = "localhost";
|
||||
const CERTIFICATE = "localhost_cert";
|
||||
|
||||
|
@ -195,7 +194,7 @@ void test(bool handshakeBeforeSecure,
|
|||
});
|
||||
}
|
||||
|
||||
ServerSocket.bind(SERVER_ADDRESS, 0, 5).then(serverReady);
|
||||
ServerSocket.bind(HOST_NAME, 0, 5).then(serverReady);
|
||||
}
|
||||
|
||||
main() {
|
||||
|
|
|
@ -15,7 +15,6 @@ import "dart:typeddata";
|
|||
import "dart:uri";
|
||||
|
||||
const String CERT_NAME = 'localhost_cert';
|
||||
const String SERVER_ADDRESS = '127.0.0.1';
|
||||
const String HOST_NAME = 'localhost';
|
||||
|
||||
/**
|
||||
|
@ -27,11 +26,11 @@ class SecurityConfiguration {
|
|||
SecurityConfiguration({bool this.secure});
|
||||
|
||||
Future<HttpServer> createServer({int backlog: 0}) =>
|
||||
secure ? HttpServer.bindSecure(SERVER_ADDRESS,
|
||||
secure ? HttpServer.bindSecure(HOST_NAME,
|
||||
0,
|
||||
backlog: backlog,
|
||||
certificateName: CERT_NAME)
|
||||
: HttpServer.bind(SERVER_ADDRESS,
|
||||
: HttpServer.bind(HOST_NAME,
|
||||
0,
|
||||
backlog);
|
||||
|
||||
|
|
Loading…
Reference in a new issue