[dart:io][windows] Implements RawSynchronousSocket

related #29343
fixes #29333

R=asiva@google.com

Review-Url: https://codereview.chromium.org/2830273002 .
This commit is contained in:
Zachary Anderson 2017-04-21 23:29:50 -07:00
parent c21653c0c4
commit bdb4eb6338
20 changed files with 472 additions and 253 deletions

View file

@ -157,7 +157,6 @@ class OverlappedBuffer {
DISALLOW_COPY_AND_ASSIGN(OverlappedBuffer);
};
// Abstract super class for holding information on listen and connected
// sockets.
class Handle : public ReferenceCounted<Handle>, public DescriptorInfoBase {

View file

@ -110,7 +110,8 @@ Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
const intptr_t kEventSize = sizeof(struct inotify_event);
const intptr_t kBufferSize = kEventSize + NAME_MAX + 1;
uint8_t buffer[kBufferSize];
intptr_t bytes = SocketBase::Read(id, buffer, kBufferSize);
intptr_t bytes =
SocketBase::Read(id, buffer, kBufferSize, SocketBase::kAsync);
if (bytes < 0) {
return DartUtils::NewDartOSError();
}

View file

@ -978,7 +978,7 @@ BOOL WINAPI SignalHandler(DWORD signal) {
while (handler != NULL) {
if (handler->signal() == signal) {
int value = 0;
SocketBase::Write(handler->fd(), &value, 1);
SocketBase::Write(handler->fd(), &value, 1, SocketBase::kAsync);
handled = true;
}
handler = handler->next();

View file

@ -353,7 +353,8 @@ void FUNCTION_NAME(Socket_Read)(Dart_NativeArguments args) {
Dart_PropagateError(result);
}
ASSERT(buffer != NULL);
intptr_t bytes_read = SocketBase::Read(socket->fd(), buffer, length);
intptr_t bytes_read =
SocketBase::Read(socket->fd(), buffer, length, SocketBase::kAsync);
if (bytes_read == length) {
Dart_SetReturnValue(args, result);
} else if (bytes_read > 0) {
@ -393,8 +394,9 @@ void FUNCTION_NAME(Socket_RecvFrom)(Dart_NativeArguments args) {
reinterpret_cast<uint8_t*>(malloc(65536));
}
RawAddr addr;
intptr_t bytes_read = SocketBase::RecvFrom(
socket->fd(), isolate_data->udp_receive_buffer, 65536, &addr);
intptr_t bytes_read =
SocketBase::RecvFrom(socket->fd(), isolate_data->udp_receive_buffer,
65536, &addr, SocketBase::kAsync);
if (bytes_read == 0) {
Dart_SetReturnValue(args, Dart_Null());
return;
@ -474,7 +476,8 @@ void FUNCTION_NAME(Socket_WriteList)(Dart_NativeArguments args) {
}
ASSERT((offset + length) <= len);
buffer += offset;
intptr_t bytes_written = SocketBase::Write(socket->fd(), buffer, length);
intptr_t bytes_written =
SocketBase::Write(socket->fd(), buffer, length, SocketBase::kAsync);
if (bytes_written >= 0) {
Dart_TypedDataReleaseData(buffer_obj);
if (short_write) {
@ -516,8 +519,8 @@ void FUNCTION_NAME(Socket_SendTo)(Dart_NativeArguments args) {
}
ASSERT((offset + length) <= len);
buffer += offset;
intptr_t bytes_written =
SocketBase::SendTo(socket->fd(), buffer, length, addr);
intptr_t bytes_written = SocketBase::SendTo(socket->fd(), buffer, length,
addr, SocketBase::kAsync);
if (bytes_written >= 0) {
Dart_TypedDataReleaseData(buffer_obj);
Dart_SetReturnValue(args, Dart_NewInteger(bytes_written));

View file

@ -21,6 +21,139 @@
namespace dart {
namespace bin {
int SocketAddress::GetType() {
if (addr_.ss.ss_family == AF_INET6) {
return TYPE_IPV6;
}
return TYPE_IPV4;
}
intptr_t SocketAddress::GetAddrLength(const RawAddr& addr) {
ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
return (addr.ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6)
: sizeof(struct sockaddr_in);
}
intptr_t SocketAddress::GetInAddrLength(const RawAddr& addr) {
ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
return (addr.ss.ss_family == AF_INET6) ? sizeof(struct in6_addr)
: sizeof(struct in_addr);
}
bool SocketAddress::AreAddressesEqual(const RawAddr& a, const RawAddr& b) {
if (a.ss.ss_family == AF_INET) {
if (b.ss.ss_family != AF_INET) {
return false;
}
return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0;
} else if (a.ss.ss_family == AF_INET6) {
if (b.ss.ss_family != AF_INET6) {
return false;
}
return memcmp(&a.in6.sin6_addr, &b.in6.sin6_addr,
sizeof(a.in6.sin6_addr)) == 0;
} else {
UNREACHABLE();
return false;
}
}
void SocketAddress::GetSockAddr(Dart_Handle obj, RawAddr* 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)) {
Dart_PropagateError(result);
}
if ((data_type != Dart_TypedData_kUint8) ||
((len != sizeof(in_addr)) && (len != sizeof(in6_addr)))) {
Dart_PropagateError(Dart_NewApiError("Unexpected type for socket address"));
}
memset(reinterpret_cast<void*>(addr), 0, sizeof(RawAddr));
if (len == sizeof(in_addr)) {
addr->in.sin_family = AF_INET;
memmove(reinterpret_cast<void*>(&addr->in.sin_addr), data, len);
} else {
ASSERT(len == sizeof(in6_addr));
addr->in6.sin6_family = AF_INET6;
memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len);
}
Dart_TypedDataReleaseData(obj);
}
int16_t SocketAddress::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;
}
void SocketAddress::SetAddrPort(RawAddr* addr, intptr_t port) {
if (addr->ss.ss_family == AF_INET) {
addr->in.sin_port = htons(port);
} else {
addr->in6.sin6_port = htons(port);
}
}
intptr_t SocketAddress::GetAddrPort(const RawAddr& addr) {
if (addr.ss.ss_family == AF_INET) {
return ntohs(addr.in.sin_port);
} else {
return ntohs(addr.in6.sin6_port);
}
}
Dart_Handle SocketAddress::ToTypedData(const RawAddr& addr) {
int len = GetInAddrLength(addr);
Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
Dart_Handle err;
if (addr.addr.sa_family == AF_INET6) {
err = Dart_ListSetAsBytes(
result, 0, reinterpret_cast<const uint8_t*>(&addr.in6.sin6_addr), len);
} else {
err = Dart_ListSetAsBytes(
result, 0, reinterpret_cast<const uint8_t*>(&addr.in.sin_addr), len);
}
if (Dart_IsError(err)) {
Dart_PropagateError(err);
}
return result;
}
CObjectUint8Array* SocketAddress::ToCObject(const RawAddr& addr) {
int in_addr_len = SocketAddress::GetInAddrLength(addr);
const void* in_addr;
CObjectUint8Array* data =
new CObjectUint8Array(CObject::NewUint8Array(in_addr_len));
if (addr.addr.sa_family == AF_INET6) {
in_addr = reinterpret_cast<const void*>(&addr.in6.sin6_addr);
} else {
in_addr = reinterpret_cast<const void*>(&addr.in.sin_addr);
}
memmove(data->Buffer(), in_addr, in_addr_len);
return data;
}
void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) {
const char* address =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));

View file

@ -63,133 +63,20 @@ class SocketAddress {
~SocketAddress() {}
int GetType() {
if (addr_.ss.ss_family == AF_INET6) {
return TYPE_IPV6;
}
return TYPE_IPV4;
}
int GetType();
const char* as_string() const { return as_string_; }
const RawAddr& addr() const { return addr_; }
static intptr_t GetAddrLength(const RawAddr& addr) {
ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
return (addr.ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6)
: sizeof(struct sockaddr_in);
}
static intptr_t GetInAddrLength(const RawAddr& addr) {
ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
return (addr.ss.ss_family == AF_INET6) ? sizeof(struct in6_addr)
: sizeof(struct in_addr);
}
static bool AreAddressesEqual(const RawAddr& a, const RawAddr& b) {
if (a.ss.ss_family == AF_INET) {
if (b.ss.ss_family != AF_INET) {
return false;
}
return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0;
} else if (a.ss.ss_family == AF_INET6) {
if (b.ss.ss_family != AF_INET6) {
return false;
}
return memcmp(&a.in6.sin6_addr, &b.in6.sin6_addr,
sizeof(a.in6.sin6_addr)) == 0;
} else {
UNREACHABLE();
return false;
}
}
static void GetSockAddr(Dart_Handle obj, RawAddr* 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)) {
Dart_PropagateError(result);
}
if ((data_type != Dart_TypedData_kUint8) ||
((len != sizeof(in_addr)) && (len != sizeof(in6_addr)))) {
Dart_PropagateError(
Dart_NewApiError("Unexpected type for socket address"));
}
memset(reinterpret_cast<void*>(addr), 0, sizeof(RawAddr));
if (len == sizeof(in_addr)) {
addr->in.sin_family = AF_INET;
memmove(reinterpret_cast<void*>(&addr->in.sin_addr), data, len);
} else {
ASSERT(len == sizeof(in6_addr));
addr->in6.sin6_family = AF_INET6;
memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len);
}
Dart_TypedDataReleaseData(obj);
}
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;
}
static void SetAddrPort(RawAddr* addr, intptr_t port) {
if (addr->ss.ss_family == AF_INET) {
addr->in.sin_port = htons(port);
} else {
addr->in6.sin6_port = htons(port);
}
}
static intptr_t GetAddrPort(const RawAddr& addr) {
if (addr.ss.ss_family == AF_INET) {
return ntohs(addr.in.sin_port);
} else {
return ntohs(addr.in6.sin6_port);
}
}
static Dart_Handle ToTypedData(const RawAddr& addr) {
int len = GetInAddrLength(addr);
Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
Dart_Handle err;
if (addr.addr.sa_family == AF_INET6) {
err = Dart_ListSetAsBytes(
result, 0, reinterpret_cast<const uint8_t*>(&addr.in6.sin6_addr),
len);
} else {
err = Dart_ListSetAsBytes(
result, 0, reinterpret_cast<const uint8_t*>(&addr.in.sin_addr), len);
}
if (Dart_IsError(err)) {
Dart_PropagateError(err);
}
return result;
}
static CObjectUint8Array* ToCObject(const RawAddr& addr) {
int in_addr_len = SocketAddress::GetInAddrLength(addr);
const void* in_addr;
CObjectUint8Array* data =
new CObjectUint8Array(CObject::NewUint8Array(in_addr_len));
if (addr.addr.sa_family == AF_INET6) {
in_addr = reinterpret_cast<const void*>(&addr.in6.sin6_addr);
} else {
in_addr = reinterpret_cast<const void*>(&addr.in.sin_addr);
}
memmove(data->Buffer(), in_addr, in_addr_len);
return data;
}
static intptr_t GetAddrLength(const RawAddr& addr);
static intptr_t GetInAddrLength(const RawAddr& addr);
static bool AreAddressesEqual(const RawAddr& a, const RawAddr& b);
static void GetSockAddr(Dart_Handle obj, RawAddr* addr);
static int16_t FromType(int type);
static void SetAddrPort(RawAddr* addr, intptr_t port);
static intptr_t GetAddrPort(const RawAddr& addr);
static Dart_Handle ToTypedData(const RawAddr& addr);
static CObjectUint8Array* ToCObject(const RawAddr& addr);
private:
char as_string_[INET6_ADDRSTRLEN];
@ -198,7 +85,6 @@ class SocketAddress {
DISALLOW_COPY_AND_ASSIGN(SocketAddress);
};
class InterfaceSocketAddress {
public:
InterfaceSocketAddress(struct sockaddr* sa,
@ -222,7 +108,6 @@ class InterfaceSocketAddress {
DISALLOW_COPY_AND_ASSIGN(InterfaceSocketAddress);
};
template <typename T>
class AddressList {
public:
@ -255,22 +140,35 @@ class SocketBase : public AllStatic {
kReverseLookupRequest = 2,
};
enum SocketOpKind {
kSync,
kAsync,
};
// TODO(dart:io): Convert these to instance methods where possible.
static bool Initialize();
static intptr_t Available(intptr_t fd);
static intptr_t Read(intptr_t fd, void* buffer, intptr_t num_bytes);
static intptr_t Write(intptr_t fd, const void* buffer, intptr_t num_bytes);
static intptr_t Read(intptr_t fd,
void* buffer,
intptr_t num_bytes,
SocketOpKind sync);
static intptr_t Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes,
SocketOpKind sync);
// Send data on a socket. The port to send to is specified in the port
// component of the passed RawAddr structure. The RawAddr structure is only
// used for datagram sockets.
static intptr_t SendTo(intptr_t fd,
const void* buffer,
intptr_t num_bytes,
const RawAddr& addr);
const RawAddr& addr,
SocketOpKind sync);
static intptr_t RecvFrom(intptr_t fd,
void* buffer,
intptr_t num_bytes,
RawAddr* addr);
RawAddr* addr,
SocketOpKind sync);
// Returns true if the given error-number is because the system was not able
// to bind the socket to a specific IP.
static bool IsBindError(intptr_t error_number);

View file

@ -62,11 +62,14 @@ intptr_t SocketBase::Available(intptr_t fd) {
}
intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@ -78,12 +81,13 @@ intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::RecvFrom(intptr_t fd,
void* buffer,
intptr_t num_bytes,
RawAddr* addr) {
RawAddr* addr,
SocketOpKind sync) {
ASSERT(fd >= 0);
socklen_t addr_len = sizeof(addr->ss);
ssize_t read_bytes = TEMP_FAILURE_RETRY(
recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@ -94,11 +98,12 @@ intptr_t SocketBase::RecvFrom(intptr_t fd,
intptr_t SocketBase::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@ -110,13 +115,14 @@ intptr_t SocketBase::Write(intptr_t fd,
intptr_t SocketBase::SendTo(intptr_t fd,
const void* buffer,
intptr_t num_bytes,
const RawAddr& addr) {
const RawAddr& addr,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t written_bytes =
TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr,
SocketAddress::GetAddrLength(addr)));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;

View file

@ -93,13 +93,16 @@ intptr_t SocketBase::Available(intptr_t fd) {
}
intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
LOG_INFO("SocketBase::Read: calling read(%ld, %p, %ld)\n", fd, buffer,
num_bytes);
ssize_t read_bytes = NO_RETRY_EXPECTED(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@ -117,7 +120,8 @@ intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::RecvFrom(intptr_t fd,
void* buffer,
intptr_t num_bytes,
RawAddr* addr) {
RawAddr* addr,
SocketOpKind sync) {
LOG_ERR("SocketBase::RecvFrom is unimplemented\n");
UNIMPLEMENTED();
return -1;
@ -126,13 +130,14 @@ intptr_t SocketBase::RecvFrom(intptr_t fd,
intptr_t SocketBase::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
LOG_INFO("SocketBase::Write: calling write(%ld, %p, %ld)\n", fd, buffer,
num_bytes);
ssize_t written_bytes = NO_RETRY_EXPECTED(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@ -150,7 +155,8 @@ intptr_t SocketBase::Write(intptr_t fd,
intptr_t SocketBase::SendTo(intptr_t fd,
const void* buffer,
intptr_t num_bytes,
const RawAddr& addr) {
const RawAddr& addr,
SocketOpKind sync) {
LOG_ERR("SocketBase::SendTo is unimplemented\n");
UNIMPLEMENTED();
return -1;

View file

@ -65,11 +65,14 @@ intptr_t SocketBase::Available(intptr_t fd) {
}
intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@ -81,12 +84,13 @@ intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::RecvFrom(intptr_t fd,
void* buffer,
intptr_t num_bytes,
RawAddr* addr) {
RawAddr* addr,
SocketOpKind sync) {
ASSERT(fd >= 0);
socklen_t addr_len = sizeof(addr->ss);
ssize_t read_bytes = TEMP_FAILURE_RETRY(
recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@ -97,11 +101,12 @@ intptr_t SocketBase::RecvFrom(intptr_t fd,
intptr_t SocketBase::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@ -113,13 +118,14 @@ intptr_t SocketBase::Write(intptr_t fd,
intptr_t SocketBase::SendTo(intptr_t fd,
const void* buffer,
intptr_t num_bytes,
const RawAddr& addr) {
const RawAddr& addr,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t written_bytes =
TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr,
SocketAddress::GetAddrLength(addr)));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;

View file

@ -64,11 +64,14 @@ intptr_t SocketBase::Available(intptr_t fd) {
}
intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@ -80,12 +83,13 @@ intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::RecvFrom(intptr_t fd,
void* buffer,
intptr_t num_bytes,
RawAddr* addr) {
RawAddr* addr,
SocketOpKind sync) {
ASSERT(fd >= 0);
socklen_t addr_len = sizeof(addr->ss);
ssize_t read_bytes = TEMP_FAILURE_RETRY(
recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@ -96,11 +100,12 @@ intptr_t SocketBase::RecvFrom(intptr_t fd,
intptr_t SocketBase::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
intptr_t num_bytes,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@ -112,13 +117,14 @@ intptr_t SocketBase::Write(intptr_t fd,
intptr_t SocketBase::SendTo(intptr_t fd,
const void* buffer,
intptr_t num_bytes,
const RawAddr& addr) {
const RawAddr& addr,
SocketOpKind sync) {
ASSERT(fd >= 0);
ssize_t written_bytes =
TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr,
SocketAddress::GetAddrLength(addr)));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;

View file

@ -76,7 +76,10 @@ intptr_t SocketBase::Available(intptr_t fd) {
}
intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes,
SocketOpKind sync) {
Handle* handle = reinterpret_cast<Handle*>(fd);
return handle->Read(buffer, num_bytes);
}
@ -85,7 +88,8 @@ intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
intptr_t SocketBase::RecvFrom(intptr_t fd,
void* buffer,
intptr_t num_bytes,
RawAddr* addr) {
RawAddr* addr,
SocketOpKind sync) {
Handle* handle = reinterpret_cast<Handle*>(fd);
socklen_t addr_len = sizeof(addr->ss);
return handle->RecvFrom(buffer, num_bytes, &addr->addr, addr_len);
@ -94,7 +98,8 @@ intptr_t SocketBase::RecvFrom(intptr_t fd,
intptr_t SocketBase::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
intptr_t num_bytes,
SocketOpKind sync) {
Handle* handle = reinterpret_cast<Handle*>(fd);
return handle->Write(buffer, num_bytes);
}
@ -103,7 +108,8 @@ intptr_t SocketBase::Write(intptr_t fd,
intptr_t SocketBase::SendTo(intptr_t fd,
const void* buffer,
intptr_t num_bytes,
const RawAddr& addr) {
const RawAddr& addr,
SocketOpKind sync) {
Handle* handle = reinterpret_cast<Handle*>(fd);
RawAddr& raw = const_cast<RawAddr&>(addr);
return handle->SendTo(buffer, num_bytes, &raw.addr,

View file

@ -143,7 +143,8 @@ void FUNCTION_NAME(SynchronousSocket_WriteList)(Dart_NativeArguments args) {
DART_CHECK_ERROR(result);
ASSERT((offset + length) <= len);
buffer += offset;
intptr_t bytes_written = SocketBase::Write(socket->fd(), buffer, length);
intptr_t bytes_written =
SynchronousSocket::Write(socket->fd(), buffer, length);
if (bytes_written >= 0) {
Dart_SetIntegerReturnValue(args, bytes_written);
} else {
@ -174,7 +175,7 @@ void FUNCTION_NAME(SynchronousSocket_ReadList)(Dart_NativeArguments args) {
DART_CHECK_ERROR(result);
uint8_t* buffer = Dart_ScopeAllocate(bytes);
intptr_t bytes_read = SocketBase::Read(socket->fd(), buffer, bytes);
intptr_t bytes_read = SynchronousSocket::Read(socket->fd(), buffer, bytes);
if (bytes_read < 0) {
Dart_SetReturnValue(args, DartUtils::NewDartOSError());
return;
@ -193,7 +194,7 @@ void FUNCTION_NAME(SynchronousSocket_Available)(Dart_NativeArguments args) {
Dart_GetNativeArgument(args, 0), &socket);
DART_CHECK_ERROR(result);
intptr_t available = SocketBase::Available(socket->fd());
intptr_t available = SynchronousSocket::Available(socket->fd());
if (available >= 0) {
Dart_SetIntegerReturnValue(args, available);
} else {
@ -208,7 +209,7 @@ void FUNCTION_NAME(SynchronousSocket_CloseSync)(Dart_NativeArguments args) {
Dart_GetNativeArgument(args, 0), &socket);
DART_CHECK_ERROR(result);
SocketBase::Close(socket->fd());
SynchronousSocket::Close(socket->fd());
socket->SetClosedFd();
}
@ -228,7 +229,7 @@ void FUNCTION_NAME(SynchronousSocket_Read)(Dart_NativeArguments args) {
uint8_t* buffer = NULL;
result = IOBuffer::Allocate(length, &buffer);
ASSERT(buffer != NULL);
intptr_t bytes_read = SocketBase::Read(socket->fd(), buffer, length);
intptr_t bytes_read = SynchronousSocket::Read(socket->fd(), buffer, length);
if (bytes_read == length) {
Dart_SetReturnValue(args, result);
} else if (bytes_read > 0) {
@ -269,7 +270,7 @@ void FUNCTION_NAME(SynchronousSocket_GetPort)(Dart_NativeArguments args) {
Dart_GetNativeArgument(args, 0), &socket);
DART_CHECK_ERROR(result);
intptr_t port = SocketBase::GetPort(socket->fd());
intptr_t port = SynchronousSocket::GetPort(socket->fd());
if (port > 0) {
Dart_SetReturnValue(args, Dart_NewInteger(port));
} else {
@ -285,7 +286,7 @@ void FUNCTION_NAME(SynchronousSocket_GetRemotePeer)(Dart_NativeArguments args) {
DART_CHECK_ERROR(result);
intptr_t port = 0;
SocketAddress* addr = SocketBase::GetRemotePeer(socket->fd(), &port);
SocketAddress* addr = SynchronousSocket::GetRemotePeer(socket->fd(), &port);
if (addr == NULL) {
Dart_SetReturnValue(args, DartUtils::NewDartOSError());
return;
@ -321,7 +322,7 @@ static void SynchronousSocketFinalizer(void* isolate_data,
void* data) {
SynchronousSocket* socket = reinterpret_cast<SynchronousSocket*>(data);
if (socket->fd() >= 0) {
SocketBase::Close(socket->fd());
SynchronousSocket::Close(socket->fd());
socket->SetClosedFd();
}
delete socket;

View file

@ -17,11 +17,11 @@ namespace bin {
class SynchronousSocket {
public:
explicit SynchronousSocket(intptr_t fd);
explicit SynchronousSocket(intptr_t fd) : fd_(fd) {}
~SynchronousSocket() { ASSERT(fd_ == kClosedFd); }
intptr_t fd() const { return fd_; }
void SetClosedFd();
void SetClosedFd() { fd_ = kClosedFd; }
static bool Initialize();
@ -32,8 +32,15 @@ class SynchronousSocket {
static Dart_Handle GetSocketIdNativeField(Dart_Handle socket_obj,
SynchronousSocket** socket);
static intptr_t Available(intptr_t fd);
static intptr_t GetPort(intptr_t fd);
static SocketAddress* GetRemotePeer(intptr_t fd, intptr_t* port);
static intptr_t Read(intptr_t fd, void* buffer, intptr_t num_bytes);
static intptr_t Write(intptr_t fd, const void* buffer, intptr_t num_bytes);
static void ShutdownRead(intptr_t fd);
static void ShutdownWrite(intptr_t fd);
static void Close(intptr_t fd);
private:
static const int kClosedFd = -1;

View file

@ -12,19 +12,12 @@
#include <errno.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/socket_base.h"
#include "platform/signal_blocker.h"
namespace dart {
namespace bin {
SynchronousSocket::SynchronousSocket(intptr_t fd) : fd_(fd) {}
void SynchronousSocket::SetClosedFd() {
fd_ = kClosedFd;
}
bool SynchronousSocket::Initialize() {
// Nothing to do on Android.
return true;
@ -63,6 +56,35 @@ intptr_t SynchronousSocket::CreateConnect(const RawAddr& addr) {
}
intptr_t SynchronousSocket::Available(intptr_t fd) {
return SocketBase::Available(fd);
}
intptr_t SynchronousSocket::GetPort(intptr_t fd) {
return SocketBase::GetPort(fd);
}
SocketAddress* SynchronousSocket::GetRemotePeer(intptr_t fd, intptr_t* port) {
return SocketBase::GetRemotePeer(fd, port);
}
intptr_t SynchronousSocket::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes) {
return SocketBase::Read(fd, buffer, num_bytes, SocketBase::kSync);
}
intptr_t SynchronousSocket::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
return SocketBase::Write(fd, buffer, num_bytes, SocketBase::kSync);
}
void SynchronousSocket::ShutdownRead(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_RD));
}
@ -72,6 +94,11 @@ void SynchronousSocket::ShutdownWrite(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_WR));
}
void SynchronousSocket::Close(intptr_t fd) {
return SocketBase::Close(fd);
}
} // namespace bin
} // namespace dart

View file

@ -12,19 +12,12 @@
#include <errno.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/socket_base.h"
#include "platform/signal_blocker.h"
namespace dart {
namespace bin {
SynchronousSocket::SynchronousSocket(intptr_t fd) : fd_(fd) {}
void SynchronousSocket::SetClosedFd() {
fd_ = kClosedFd;
}
bool SynchronousSocket::Initialize() {
// Nothing to do on Fuchsia.
return true;
@ -63,6 +56,35 @@ intptr_t SynchronousSocket::CreateConnect(const RawAddr& addr) {
}
intptr_t SynchronousSocket::Available(intptr_t fd) {
return SocketBase::Available(fd);
}
intptr_t SynchronousSocket::GetPort(intptr_t fd) {
return SocketBase::GetPort(fd);
}
SocketAddress* SynchronousSocket::GetRemotePeer(intptr_t fd, intptr_t* port) {
return SocketBase::GetRemotePeer(fd, port);
}
intptr_t SynchronousSocket::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes) {
return SocketBase::Read(fd, buffer, num_bytes, SocketBase::kSync);
}
intptr_t SynchronousSocket::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
return SocketBase::Write(fd, buffer, num_bytes, SocketBase::kSync);
}
void SynchronousSocket::ShutdownRead(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_RD));
}
@ -72,6 +94,11 @@ void SynchronousSocket::ShutdownWrite(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_WR));
}
void SynchronousSocket::Close(intptr_t fd) {
return SocketBase::Close(fd);
}
} // namespace bin
} // namespace dart

View file

@ -12,19 +12,12 @@
#include <errno.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/socket_base.h"
#include "platform/signal_blocker.h"
namespace dart {
namespace bin {
SynchronousSocket::SynchronousSocket(intptr_t fd) : fd_(fd) {}
void SynchronousSocket::SetClosedFd() {
fd_ = kClosedFd;
}
bool SynchronousSocket::Initialize() {
// Nothing to do on Linux.
return true;
@ -63,6 +56,35 @@ intptr_t SynchronousSocket::CreateConnect(const RawAddr& addr) {
}
intptr_t SynchronousSocket::Available(intptr_t fd) {
return SocketBase::Available(fd);
}
intptr_t SynchronousSocket::GetPort(intptr_t fd) {
return SocketBase::GetPort(fd);
}
SocketAddress* SynchronousSocket::GetRemotePeer(intptr_t fd, intptr_t* port) {
return SocketBase::GetRemotePeer(fd, port);
}
intptr_t SynchronousSocket::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes) {
return SocketBase::Read(fd, buffer, num_bytes, SocketBase::kSync);
}
intptr_t SynchronousSocket::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
return SocketBase::Write(fd, buffer, num_bytes, SocketBase::kSync);
}
void SynchronousSocket::ShutdownRead(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_RD));
}
@ -72,6 +94,11 @@ void SynchronousSocket::ShutdownWrite(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_WR));
}
void SynchronousSocket::Close(intptr_t fd) {
return SocketBase::Close(fd);
}
} // namespace bin
} // namespace dart

View file

@ -12,16 +12,15 @@
#include <errno.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/socket_base.h"
#include "platform/signal_blocker.h"
namespace dart {
namespace bin {
SynchronousSocket::SynchronousSocket(intptr_t fd) : fd_(fd) {}
void SynchronousSocket::SetClosedFd() {
fd_ = kClosedFd;
bool SynchronousSocket::Initialize() {
// Nothing to do on Linux.
return true;
}
@ -60,6 +59,35 @@ intptr_t SynchronousSocket::CreateConnect(const RawAddr& addr) {
}
intptr_t SynchronousSocket::Available(intptr_t fd) {
return SocketBase::Available(fd);
}
intptr_t SynchronousSocket::GetPort(intptr_t fd) {
return SocketBase::GetPort(fd);
}
SocketAddress* SynchronousSocket::GetRemotePeer(intptr_t fd, intptr_t* port) {
return SocketBase::GetRemotePeer(fd, port);
}
intptr_t SynchronousSocket::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes) {
return SocketBase::Read(fd, buffer, num_bytes, SocketBase::kSync);
}
intptr_t SynchronousSocket::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
return SocketBase::Write(fd, buffer, num_bytes, SocketBase::kSync);
}
void SynchronousSocket::ShutdownRead(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_RD));
}
@ -69,6 +97,11 @@ void SynchronousSocket::ShutdownWrite(intptr_t fd) {
VOID_NO_RETRY_EXPECTED(shutdown(fd, SHUT_WR));
}
void SynchronousSocket::Close(intptr_t fd) {
return SocketBase::Close(fd);
}
} // namespace bin
} // namespace dart

View file

@ -7,69 +7,105 @@
#include "platform/globals.h"
#if defined(HOST_OS_WINDOWS)
#include "bin/socket_base.h"
#include "bin/sync_socket.h"
#include "bin/builtin.h"
#include "bin/log.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
// #define SOCKET_LOG_ERROR 1
// define SOCKET_LOG_ERROR to get log messages only for errors.
#if defined(SOCKET_LOG_ERROR)
#define LOG_ERR(msg, ...) \
{ \
int err = errno; \
Log::PrintErr("Dart Socket ERROR: %s:%d: " msg, __FILE__, __LINE__, \
##__VA_ARGS__); \
errno = err; \
}
#else
#define LOG_ERR(msg, ...)
#endif // defined(SOCKET_LOG_ERROR)
namespace dart {
namespace bin {
SynchronousSocket::SynchronousSocket(intptr_t fd) {
LOG_ERR("SynchronousSocket is unimplemented\n");
UNIMPLEMENTED();
}
bool SynchronousSocket::Initialize() {
LOG_ERR("SynchronousSocket::Initialize is unimplemented\n");
UNIMPLEMENTED();
return false;
return SocketBase::Initialize();
}
void SynchronousSocket::SetClosedFd() {
LOG_ERR("SynchronousSocket::SetClosedFd is unimplemented\n");
UNIMPLEMENTED();
static intptr_t Create(const RawAddr& addr) {
const intptr_t type = SOCK_STREAM;
SOCKET s = WSASocket(addr.ss.ss_family, type, 0, NULL, 0, 0);
return (s == INVALID_SOCKET) ? -1 : s;
}
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
SOCKET socket = static_cast<SOCKET>(fd);
intptr_t result =
connect(socket, &addr.addr, SocketAddress::GetAddrLength(addr));
return (result == SOCKET_ERROR) ? -1 : socket;
}
intptr_t SynchronousSocket::CreateConnect(const RawAddr& addr) {
LOG_ERR("SynchronousSocket::CreateConnect is unimplemented\n");
UNIMPLEMENTED();
return -1;
intptr_t fd = Create(addr);
return (fd < 0) ? fd : Connect(fd, addr);
}
intptr_t SynchronousSocket::Available(intptr_t fd) {
SOCKET socket = static_cast<SOCKET>(fd);
DWORD available;
intptr_t result = ioctlsocket(socket, FIONREAD, &available);
return (result == SOCKET_ERROR) ? -1 : static_cast<intptr_t>(available);
}
intptr_t SynchronousSocket::GetPort(intptr_t fd) {
SOCKET socket = static_cast<SOCKET>(fd);
RawAddr raw;
socklen_t size = sizeof(raw);
if (getsockname(socket, &raw.addr, &size) == SOCKET_ERROR) {
return 0;
}
return SocketAddress::GetAddrPort(raw);
}
SocketAddress* SynchronousSocket::GetRemotePeer(intptr_t fd, intptr_t* port) {
SOCKET socket = static_cast<SOCKET>(fd);
RawAddr raw;
socklen_t size = sizeof(raw);
if (getpeername(socket, &raw.addr, &size)) {
return NULL;
}
*port = SocketAddress::GetAddrPort(raw);
// Clear the port before calling WSAAddressToString as WSAAddressToString
// includes the port in the formatted string.
SocketAddress::SetAddrPort(&raw, 0);
return new SocketAddress(&raw.addr);
}
intptr_t SynchronousSocket::Read(intptr_t fd,
void* buffer,
intptr_t num_bytes) {
SOCKET socket = static_cast<SOCKET>(fd);
return recv(socket, reinterpret_cast<char*>(buffer), num_bytes, 0);
}
intptr_t SynchronousSocket::Write(intptr_t fd,
const void* buffer,
intptr_t num_bytes) {
SOCKET socket = static_cast<SOCKET>(fd);
return send(socket, reinterpret_cast<const char*>(buffer), num_bytes, 0);
}
void SynchronousSocket::ShutdownRead(intptr_t fd) {
LOG_ERR("SynchronousSocket::ShutdownRead is unimplemented\n");
UNIMPLEMENTED();
SOCKET socket = static_cast<SOCKET>(fd);
shutdown(socket, SD_RECEIVE);
}
void SynchronousSocket::ShutdownWrite(intptr_t fd) {
LOG_ERR("SynchronousSocket::ShutdownWrite is unimplemented\n");
UNIMPLEMENTED();
SOCKET socket = static_cast<SOCKET>(fd);
shutdown(socket, SD_SEND);
}
void SynchronousSocket::Close(intptr_t fd) {
SOCKET socket = static_cast<SOCKET>(fd);
closesocket(socket);
}
} // namespace bin
} // namespace dart

View file

@ -397,7 +397,6 @@ Future testShutdown() async {
// Throws exception when the socket is closed for RECEIVE.
Expect.throws(
() => socket.readSync(data.length), (e) => e is SocketException);
Expect.isTrue(socket.available() == 0);
socket.closeSync();
// Close the socket for writing and try to do a write. This should cause an

View file

@ -9,7 +9,6 @@
io/raw_socket_test: Pass, RuntimeError # Issue 28288
io/http_close_test: Pass, RuntimeError # Issue 28380
io/raw_synchronous_socket_test: Pass, RuntimeError # Issue 29343
packages_file_test: Skip # Issue 26715
packages_file_test/none: Skip # contains no tests.
@ -232,7 +231,6 @@ io/process_stdin_transform_unsubscribe_test: Pass, Timeout # Issue #28558
io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
io/skipping_dart2js_compilations_test: Fail # Issue 19551.
io/socket_info_ipv6_test: RuntimeError # Issue 27876
io/raw_synchronous_socket_test: Crash # Issue 29333, currently unsupported
[ $system == windows && $compiler == dart2analyzer ]
package/package_isolate_test: Crash # Issue 28645