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:
ajohnsen@google.com 2013-04-23 09:36:18 +00:00
parent 029e343b42
commit b33d142414
37 changed files with 843 additions and 428 deletions

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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");

View file

@ -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.

View file

@ -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

View file

@ -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();

View file

@ -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)

View file

@ -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;

View file

@ -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");

View file

@ -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',

View file

@ -19,11 +19,6 @@ void testBadHostName() {
});
}
void InitializeSSL() {
SecureSocket.initialize();
}
void main() {
testBadHostName();
Expect.throws(InitializeSSL);
}

View file

@ -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) {

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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) {

View file

@ -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"));

View file

@ -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) {

View 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();
}

View file

@ -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() {

View file

@ -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);