[io] Support Unix domain sockets on Windows

Basic support for Unix domain sockets on Windows within
the limitations of the operating system itself: no 
support for abstract addresses, datagram or 
packet sockets and ancillary data.

This also fixes File::GetType on Windows to correctly
identify reparse points representing AF_UNIX sockets
as such, rather then identify them as links.

Finally, it is worth noting that there is an existing
discrepancy between POSIX OSes and Windows: on POSIX OSes
File(sockPath).existsSync() returns true, but on Windows the 
same code returns false because Unix domain sockets are not 
considered regular files by stat. 

This CL does a bunch of refactoring around RawAddr class which
surves as a wrapper around various structures in sockaddr_* family.
Distinguishing anonymous AF_UNIX address from abstract AF_UNIX
address requires passing around the length of the address
structure. Thus we incorporate this information into
RawAddr. This will also make possible to properly support
full-range of abstract AF_UNIX addresses in the future because
supporting these requires properly handling embedded NUL bytes.
(See https://github.com/dart-lang/sdk/issues/46158).

Fixes https://github.com/dart-lang/sdk/issues/41161

TEST=standalone/io/unix_socket

Cq-Include-Trybots: luci.dart.try:vm-fuchsia-release-x64-try
Change-Id: I016cb33ebdd62f0cac1ae97d822105366a6a6964
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/457720
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
Slava Egorov
2025-10-29 05:25:24 -07:00
committed by Commit Queue
parent de2737affe
commit e50d3b98a3
25 changed files with 515 additions and 515 deletions
+12
View File
@@ -4,6 +4,18 @@
### Libraries
#### `dart:io`
- Added support for Unix domain sockets (`AF_UNIX`) on Windows. Support is
restricted to subset of features supported by the OS. Windows currently does
not support the following features for `AF_UNIX` sockets: datagram sockets,
ancillary data or abstract socket addresses. Unix domain sockets are
represented in the file-system using _reparse points_ which leads to some
discrepancies in the behavior of `dart:io` APIs: for example
`File(socketPath).existsSync()` will return `true` on POSIX operating systems,
but `false` on Windows. Use `FileSystemEntity.typeSync()` instead to get
portable behavior.
#### `dart:js_util`
- dart2wasm no longer supports `dart:js_util`. Any code that imports
+3 -2
View File
@@ -127,9 +127,10 @@ intptr_t IOHandle::Write(const void* buffer, intptr_t num_bytes) {
return written_bytes;
}
intptr_t IOHandle::Accept(struct sockaddr* addr, socklen_t* addrlen) {
intptr_t IOHandle::Accept(RawAddr* addr) {
MutexLocker ml(&mutex_);
const intptr_t socket = NO_RETRY_EXPECTED(accept(fd_, addr, addrlen));
const intptr_t socket =
NO_RETRY_EXPECTED(accept(fd_, &addr->addr, &addr->size));
const int err = errno;
LOG_INFO("IOHandle::Accept: fd = %ld. socket = %ld\n", fd_, socket);
+2 -1
View File
@@ -26,6 +26,7 @@ namespace dart {
namespace bin {
class DescriptorInfo;
struct RawAddr;
class IOHandle : public ReferenceCounted<IOHandle> {
public:
@@ -46,7 +47,7 @@ class IOHandle : public ReferenceCounted<IOHandle> {
// the Dart thread.
intptr_t Read(void* buffer, intptr_t num_bytes);
intptr_t Write(const void* buffer, intptr_t num_bytes);
intptr_t Accept(struct sockaddr* addr, socklen_t* addrlen);
intptr_t Accept(RawAddr* addr);
intptr_t AvailableBytes();
// Called from the EventHandler thread.
+30 -43
View File
@@ -68,25 +68,17 @@ OverlappedBuffer::OverlappedBuffer(Handle* handle,
: buflen_(buffer_size), operation_(operation), handle_(handle) {
memset(GetBufferStart(), 0, GetBufferSize());
if (operation == kRecvFrom) {
// Reserve part of the buffer for the length of source sockaddr
// and source sockaddr.
const int kAdditionalSize =
sizeof(struct sockaddr_storage) + sizeof(socklen_t);
ASSERT(buflen_ > kAdditionalSize);
buflen_ -= kAdditionalSize;
from_len_addr_ =
reinterpret_cast<socklen_t*>(GetBufferStart() + GetBufferSize());
*from_len_addr_ = sizeof(struct sockaddr_storage);
from_ = reinterpret_cast<struct sockaddr*>(from_len_addr_ + 1);
// Reserve part of the buffer for the length of source address.
ASSERT(buflen_ > sizeof(RawAddr));
buflen_ -= sizeof(RawAddr);
from_ = reinterpret_cast<RawAddr*>(GetBufferStart() + GetBufferSize());
// WSARecv needs to know how many bytes it can write.
from_->size = sizeof(sockaddr_storage);
} else {
from_len_addr_ = nullptr;
from_ = nullptr;
}
index_ = 0;
data_length_ = 0;
if (operation_ == kAccept) {
client_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
// Retain handle for the duration of the operation.
handle->Retain();
@@ -114,8 +106,13 @@ std::unique_ptr<OverlappedBuffer> OverlappedBuffer::AllocateBuffer(
}
std::unique_ptr<OverlappedBuffer> OverlappedBuffer::AllocateAcceptBuffer(
Handle* handle) {
return AllocateBuffer(handle, 2 * kAcceptExAddressStorageSize, kAccept);
Handle* handle,
ADDRESS_FAMILY sa_family) {
auto result =
AllocateBuffer(handle, 2 * kAcceptExAddressStorageSize, kAccept);
result->client_ =
socket(sa_family, SOCK_STREAM, sa_family == AF_UNIX ? 0 : IPPROTO_TCP);
return result;
}
std::unique_ptr<OverlappedBuffer> OverlappedBuffer::AllocateReadBuffer(
@@ -129,7 +126,7 @@ std::unique_ptr<OverlappedBuffer> OverlappedBuffer::AllocateRecvFromBuffer(
int buffer_size) {
// For calling recvfrom additional buffer space is needed for the source
// address information.
buffer_size += sizeof(socklen_t) + sizeof(struct sockaddr_storage);
buffer_size += sizeof(RawAddr);
return AllocateBuffer(handle, buffer_size, kRecvFrom);
}
@@ -405,8 +402,7 @@ bool Handle::IssueWriteLocked(MonitorLocker* ml,
bool Handle::IssueSendToLocked(MonitorLocker* ml,
std::unique_ptr<OverlappedBuffer> buffer,
struct sockaddr* sa,
socklen_t sa_len) {
const RawAddr& addr) {
return false;
}
@@ -493,7 +489,7 @@ void SocketHandle::HandleIssueError() {
}
bool ListenSocket::IssueAcceptLocked(MonitorLocker* ml) {
auto buffer = OverlappedBuffer::AllocateAcceptBuffer(this);
auto buffer = OverlappedBuffer::AllocateAcceptBuffer(this, sa_family_);
DWORD received;
BOOL ok;
ok = EventHandler::delegate()->accept_ex()(
@@ -546,12 +542,14 @@ void ListenSocket::AcceptComplete(std::unique_ptr<OverlappedBuffer> buffer) {
buffer->GetBufferStart(), 0, kAcceptExAddressStorageSize,
kAcceptExAddressStorageSize, &local_addr, &local_addr_length,
&remote_addr, &remote_addr_length);
RawAddr* raw_remote_addr = new RawAddr;
memmove(raw_remote_addr, remote_addr, remote_addr_length);
auto raw_remote_addr = std::make_unique<RawAddr>();
memmove(&raw_remote_addr->addr, remote_addr, remote_addr_length);
raw_remote_addr->size = remote_addr_length;
// Insert the accepted socket into the list.
ClientSocket* client_socket =
new ClientSocket(client, std::unique_ptr<RawAddr>(raw_remote_addr));
new ClientSocket(client, std::move(raw_remote_addr));
client_socket->mark_connected();
if (accepted_head_ == nullptr) {
accepted_head_ = client_socket;
@@ -662,24 +660,14 @@ intptr_t Handle::Read(void* buffer, intptr_t num_bytes) {
return num_bytes;
}
intptr_t Handle::RecvFrom(void* buffer,
intptr_t num_bytes,
struct sockaddr* sa,
socklen_t sa_len) {
intptr_t Handle::RecvFrom(void* buffer, intptr_t num_bytes, RawAddr* from) {
MonitorLocker ml(&monitor_);
if (data_ready_ == nullptr) {
return 0;
}
num_bytes =
data_ready_->Read(buffer, Utils::Minimum<intptr_t>(num_bytes, INT_MAX));
if (data_ready_->from()->sa_family == AF_INET) {
ASSERT(sa_len >= sizeof(struct sockaddr_in));
memmove(sa, data_ready_->from(), sizeof(struct sockaddr_in));
} else {
ASSERT(data_ready_->from()->sa_family == AF_INET6);
ASSERT(sa_len >= sizeof(struct sockaddr_in6));
memmove(sa, data_ready_->from(), sizeof(struct sockaddr_in6));
}
*from = *data_ready_->from();
// Always dispose of the buffer, as UDP messages must be read in their
// entirety to match how recvfrom works in a socket.
data_ready_ = nullptr;
@@ -709,8 +697,7 @@ intptr_t Handle::Write(const void* data, intptr_t num_bytes) {
intptr_t Handle::SendTo(const void* data,
intptr_t num_bytes,
struct sockaddr* sa,
socklen_t sa_len) {
const RawAddr& addr) {
MonitorLocker ml(&monitor_);
if (HasPendingWrite() || IsClosed()) {
return 0;
@@ -726,7 +713,7 @@ intptr_t Handle::SendTo(const void* data,
}
auto buffer = OverlappedBuffer::AllocateSendToBuffer(this, num_bytes);
buffer->Write(data, num_bytes);
if (!IssueSendToLocked(&ml, std::move(buffer), sa, sa_len)) {
if (!IssueSendToLocked(&ml, std::move(buffer), addr)) {
return -1;
}
return num_bytes;
@@ -975,14 +962,14 @@ bool ClientSocket::PopulateRemoteAddr(RawAddr& addr) {
bool DatagramSocket::IssueSendToLocked(MonitorLocker* ml,
std::unique_ptr<OverlappedBuffer> buffer,
struct sockaddr* sa,
socklen_t sa_len) {
const RawAddr& addr) {
ASSERT(!HasPendingWrite());
ASSERT(buffer->operation() == OverlappedBuffer::kSendTo);
pending_write_ = buffer.get();
int rc = WSASendTo(socket(), pending_write_->GetWASBUF(), 1, nullptr, 0, sa,
sa_len, pending_write_->GetCleanOverlapped(), nullptr);
int rc = WSASendTo(socket(), pending_write_->GetWASBUF(), 1, nullptr, 0,
&addr.addr, addr.size,
pending_write_->GetCleanOverlapped(), nullptr);
if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
buffer.release(); // HandleIOCompletion will take ownership.
return true;
@@ -1001,7 +988,7 @@ bool DatagramSocket::IssueRecvFromLocked(MonitorLocker* ml) {
pending_read_ = buffer.get();
DWORD flags = 0;
int rc = WSARecvFrom(socket(), buffer->GetWASBUF(), 1, nullptr, &flags,
buffer->from(), buffer->from_len_addr(),
&buffer->from()->addr, &buffer->from()->size,
buffer->GetCleanOverlapped(), nullptr);
if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
buffer.release(); // HandleIOCompletion will take ownership.
+14 -18
View File
@@ -47,7 +47,9 @@ class OverlappedBuffer {
kConnect
};
static std::unique_ptr<OverlappedBuffer> AllocateAcceptBuffer(Handle* handle);
static std::unique_ptr<OverlappedBuffer> AllocateAcceptBuffer(
Handle* handle,
ADDRESS_FAMILY sa_family);
static std::unique_ptr<OverlappedBuffer> AllocateReadBuffer(Handle* handle,
int buffer_size);
static std::unique_ptr<OverlappedBuffer> AllocateRecvFromBuffer(
@@ -86,9 +88,7 @@ class OverlappedBuffer {
SOCKET client() const { return client_; }
char* GetBufferStart() { return reinterpret_cast<char*>(&buffer_data_); }
int GetBufferSize() const { return buflen_; }
struct sockaddr* from() const { return from_; }
socklen_t* from_len_addr() const { return from_len_addr_; }
socklen_t from_len() const { return from_ == nullptr ? 0 : *from_len_addr_; }
RawAddr* from() const { return from_; }
// Returns the address of the OVERLAPPED structure with all fields
// initialized to zero.
@@ -144,8 +144,7 @@ class OverlappedBuffer {
// For the recvfrom operation additional storace is allocated for the
// source sockaddr.
socklen_t* from_len_addr_; // Pointer to source sockaddr size storage.
struct sockaddr* from_; // Pointer to source sockaddr storage.
RawAddr* from_;
// Buffer for recv/send/AcceptEx. This must be at the end of the
// object as the object is allocated larger than it's definition
@@ -174,15 +173,11 @@ class Handle : public ReferenceCounted<Handle>, public DescriptorInfoBase {
intptr_t Available();
bool DataReady();
intptr_t Read(void* buffer, intptr_t num_bytes);
intptr_t RecvFrom(void* buffer,
intptr_t num_bytes,
struct sockaddr* sa,
socklen_t addr_len);
intptr_t RecvFrom(void* buffer, intptr_t num_bytes, RawAddr* from);
virtual intptr_t Write(const void* buffer, intptr_t num_bytes);
virtual intptr_t SendTo(const void* buffer,
intptr_t num_bytes,
struct sockaddr* sa,
socklen_t sa_len);
const RawAddr& addr);
// Internal interface used by the event handler.
virtual bool IssueReadLocked(MonitorLocker* ml);
@@ -274,8 +269,7 @@ class Handle : public ReferenceCounted<Handle>, public DescriptorInfoBase {
std::unique_ptr<OverlappedBuffer> buffer);
virtual bool IssueSendToLocked(MonitorLocker* ml,
std::unique_ptr<OverlappedBuffer> buffer,
struct sockaddr* sa,
socklen_t sa_len);
const RawAddr& addr);
int flags_ = 0;
@@ -375,8 +369,9 @@ class SocketHandle : public Handle {
// Information on listen sockets.
class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
public:
explicit ListenSocket(intptr_t s)
explicit ListenSocket(intptr_t s, ADDRESS_FAMILY sa_family)
: DescriptorInfoMultipleMixin(s, kListenSocket),
sa_family_(sa_family),
pending_accept_count_(0),
accepted_head_(nullptr),
accepted_tail_(nullptr),
@@ -409,6 +404,8 @@ class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
bool IssueAcceptLocked(MonitorLocker* ml);
ADDRESS_FAMILY sa_family_;
// The number of asynchronous `IssueAccept` operations which haven't completed
// yet.
int pending_accept_count_;
@@ -429,7 +426,7 @@ class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
class ClientSocket : public DescriptorInfoSingleMixin<SocketHandle> {
public:
explicit ClientSocket(intptr_t s,
std::unique_ptr<RawAddr> remote_addr = nullptr)
std::unique_ptr<RawAddr>&& remote_addr = nullptr)
: DescriptorInfoSingleMixin(s, kClientSocket),
next_(nullptr),
connected_(false),
@@ -508,8 +505,7 @@ class DatagramSocket : public DescriptorInfoSingleMixin<SocketHandle> {
private:
virtual bool IssueSendToLocked(MonitorLocker* ml,
std::unique_ptr<OverlappedBuffer> buffer,
sockaddr* sa,
socklen_t sa_len);
const RawAddr& addr);
DISALLOW_COPY_AND_ASSIGN(DatagramSocket);
};
+30
View File
@@ -1128,11 +1128,41 @@ File::StdioHandleType File::GetStdioHandleType(int fd) {
return kPipe;
}
static BOOL GetReparsePointTag(const wchar_t* path, DWORD* tag) {
WIN32_FIND_DATA data;
HANDLE result = FindFirstFileW(path, &data);
if (result == INVALID_HANDLE_VALUE) {
return FALSE;
}
FindClose(result);
if ((data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
// The meaning of |dwReserved0| is documented in
// https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags
*tag = data.dwReserved0;
return TRUE;
}
return FALSE;
}
File::Type File::GetType(const wchar_t* path, bool follow_links) {
DWORD attributes = GetFileAttributesW(path);
if (attributes == INVALID_FILE_ATTRIBUTES) {
return File::kDoesNotExist;
} else if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
DWORD tag;
if (!GetReparsePointTag(path, &tag)) {
return File::kDoesNotExist;
}
// We treat only Unix domain sockets specially - all other reparse points
// we treat as links, even though there are many other types of them. See:
// https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags
if (tag == IO_REPARSE_TAG_AF_UNIX) {
return File::kIsSock;
}
if (follow_links) {
HANDLE target_handle = CreateFileW(
path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+58 -53
View File
@@ -92,7 +92,7 @@ void ListeningSocketRegistry::RemoveByFd(Socket* fd) {
}
Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object,
RawAddr addr,
const RawAddr& addr,
intptr_t backlog,
bool v6_only,
bool shared) {
@@ -209,42 +209,39 @@ Dart_Handle ListeningSocketRegistry::CreateUnixDomainBindListen(
return result;
}
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
// Abstract unix domain socket doesn't exist in file system.
if (File::Exists(namespc, addr.un.sun_path) && path[0] != '@') {
#else
if (File::Exists(namespc, addr.un.sun_path)) {
#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
if (unix_domain_sockets_ != nullptr) {
// If there is a socket listening on this file. Ensure
// that it was created with `shared` mode and current `shared`
// is also true.
OSSocket* os_socket = unix_domain_sockets_;
OSSocket* os_socket_same_addr =
FindOSSocketWithPath(os_socket, namespc, addr.un.sun_path);
if (os_socket_same_addr != nullptr) {
if (!os_socket_same_addr->shared || !shared) {
OSError os_error(-1,
"The shared flag to bind() needs to be `true` if "
"binding multiple times on the same path.",
OSError::kUnknown);
return DartUtils::NewDartOSError(&os_error);
}
// This socket creation is the exact same as the one which originally
// created the socket. Feed the same fd and store it into the native
// field of dart socket_object. Sockets here will share same fd but
// contain a different port() through EventHandler_SendData.
Socket* socketfd = new Socket(os_socket_same_addr->fd);
os_socket_same_addr->ref_count++;
// We set as a side-effect the file descriptor on the dart
// socket_object.
Socket::ReuseSocketIdNativeField(socket_object, socketfd,
Socket::kFinalizerListening);
InsertByFd(socketfd, os_socket_same_addr);
return Dart_True();
if (unix_domain_sockets_ != nullptr) {
// If there is a socket listening on this file. Ensure
// that it was created with `shared` mode and current `shared`
// is also true.
OSSocket* os_socket_same_addr =
FindMatchingUnixDomainSocket(unix_domain_sockets_, namespc, addr);
if (os_socket_same_addr != nullptr) {
if (!os_socket_same_addr->shared || !shared) {
OSError os_error(-1,
"The shared flag to bind() needs to be `true` if "
"binding multiple times on the same path.",
OSError::kUnknown);
return DartUtils::NewDartOSError(&os_error);
}
// This socket creation is the exact same as the one which originally
// created the socket. Feed the same fd and store it into the native
// field of dart socket_object. Sockets here will share same fd but
// contain a different port() through EventHandler_SendData.
Socket* socketfd = new Socket(os_socket_same_addr->fd);
os_socket_same_addr->ref_count++;
// We set as a side-effect the file descriptor on the dart
// socket_object.
Socket::ReuseSocketIdNativeField(socket_object, socketfd,
Socket::kFinalizerListening);
InsertByFd(socketfd, os_socket_same_addr);
return Dart_True();
}
}
if (addr.is_pathname_unix_socket() &&
File::GetType(namespc, addr.un.sun_path, /*follow_links=*/false) !=
File::kDoesNotExist) {
// Unix domain socket by default doesn't allow binding to an existing file.
// An error (EADDRINUSE) will be returned back. However, hanging is noticed
// on Android so we throw an exception for all platforms.
@@ -255,11 +252,13 @@ Dart_Handle ListeningSocketRegistry::CreateUnixDomainBindListen(
// There is no socket listening on that path, so we create new one.
intptr_t fd = ServerSocket::CreateUnixDomainBindListen(addr, backlog);
if (fd < 0) {
return DartUtils::NewDartOSError();
}
if (!ServerSocket::StartAccept(fd)) {
OSError os_error(-1, "Failed to start accept", OSError::kUnknown);
return DartUtils::NewDartOSError(&os_error);
}
Socket* socketfd = new Socket(fd);
OSSocket* os_socket =
new OSSocket(addr, -1, false, shared, socketfd, namespc);
@@ -420,7 +419,7 @@ void FUNCTION_NAME(Socket_CreateBindConnect)(Dart_NativeArguments args) {
void FUNCTION_NAME(Socket_CreateUnixDomainBindConnect)(
Dart_NativeArguments args) {
#if defined(DART_HOST_OS_WINDOWS) || defined(DART_HOST_OS_FUCHSIA)
#if defined(DART_HOST_OS_FUCHSIA)
OSError os_error(
-1, "Unix domain sockets are not available on this operating system.",
OSError::kUnknown);
@@ -465,7 +464,7 @@ void FUNCTION_NAME(Socket_CreateUnixDomainBindConnect)(
}
void FUNCTION_NAME(Socket_CreateUnixDomainConnect)(Dart_NativeArguments args) {
#if defined(DART_HOST_OS_WINDOWS) || defined(DART_HOST_OS_FUCHSIA)
#if defined(DART_HOST_OS_FUCHSIA)
OSError os_error(
-1, "Unix domain sockets are not available on this operating system.",
OSError::kUnknown);
@@ -638,8 +637,9 @@ void FUNCTION_NAME(Socket_RecvFrom)(Dart_NativeArguments args) {
type = IPv6;
}
// Format the address to a string using the numeric format.
char numeric_address[INET6_ADDRSTRLEN];
SocketBase::FormatNumericAddress(addr, numeric_address, INET6_ADDRSTRLEN);
char numeric_address[SocketAddress::kMaxAddressStringLength];
SocketBase::FormatNumericAddress(addr, numeric_address,
ARRAY_SIZE(numeric_address));
// Create a Datagram object with the data and sender address and port.
const int kNumArgs = 5;
@@ -910,8 +910,7 @@ void FUNCTION_NAME(Socket_GetRemotePeer)(Dart_NativeArguments args) {
entry = Dart_NewList(2);
} else {
entry = Dart_NewList(3);
RawAddr raw = addr->addr();
Dart_ListSetAt(entry, 2, SocketAddress::ToTypedData(raw));
Dart_ListSetAt(entry, 2, SocketAddress::ToTypedData(addr->addr()));
}
Dart_ListSetAt(entry, 0, Dart_NewInteger(type));
Dart_ListSetAt(entry, 1, Dart_NewStringFromCString(addr->as_string()));
@@ -1022,7 +1021,7 @@ void FUNCTION_NAME(ServerSocket_CreateBindListen)(Dart_NativeArguments args) {
void FUNCTION_NAME(ServerSocket_CreateUnixDomainBindListen)(
Dart_NativeArguments args) {
#if defined(DART_HOST_OS_WINDOWS)
#if defined(DART_HOST_OS_FUCHSIA)
OSError os_error(
-1, "Unix domain sockets are not available on this operating system.",
OSError::kUnknown);
@@ -1084,7 +1083,7 @@ CObject* Socket::LookupRequest(const CObjectArray& request) {
new CObjectString(CObject::NewString(addr->as_string()));
entry->SetAt(1, as_string);
RawAddr raw = addr->addr();
const auto& raw = addr->addr();
CObjectUint8Array* data = SocketAddress::ToCObject(raw);
entry->SetAt(2, data);
@@ -1113,11 +1112,13 @@ CObject* Socket::ReverseLookupRequest(const CObjectArray& request) {
memset(reinterpret_cast<void*>(&addr), 0, sizeof(RawAddr));
if (len == sizeof(in_addr)) {
addr.in.sin_family = AF_INET;
addr.size = sizeof(sockaddr_in);
memmove(reinterpret_cast<void*>(&addr.in.sin_addr), addr_object.Buffer(),
len);
} else {
ASSERT(len == sizeof(in6_addr));
addr.in6.sin6_family = AF_INET6;
addr.size = sizeof(sockaddr_in6);
memmove(reinterpret_cast<void*>(&addr.in6.sin6_addr),
addr_object.Buffer(), len);
}
@@ -1160,7 +1161,7 @@ CObject* Socket::ListInterfacesRequest(const CObjectArray& request) {
new CObjectString(CObject::NewString(addr->as_string()));
entry->SetAt(1, as_string);
RawAddr raw = addr->addr();
const auto& raw = addr->addr();
CObjectUint8Array* data = SocketAddress::ToCObject(raw);
entry->SetAt(2, data);
@@ -1671,21 +1672,25 @@ void FUNCTION_NAME(ResourceHandleImpl_toRawSocket)(Dart_NativeArguments args) {
Dart_GetField(handle_object, DartUtils::NewString("_handle")));
intptr_t fd = DartUtils::GetIntegerValue(handle_field);
SocketAddress* socket_address = reinterpret_cast<SocketAddress*>(
Dart_ScopeAllocate(sizeof(SocketAddress)));
ASSERT(socket_address != nullptr);
SocketBase::GetSocketName(fd, socket_address);
RawAddr raw;
if (!SocketBase::GetSocketName(fd, &raw)) {
OSError os_error(-1, "Failed to get socket address", OSError::kUnknown);
Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
return;
}
const SocketAddress socket_address(raw);
// return a list describing socket_address: (type, hostname, typed_data_addr,
// fd)
Dart_Handle list = ThrowIfError(Dart_NewList(4));
ThrowIfError(Dart_ListSetAt(
list, 0, ThrowIfError(Dart_NewInteger(socket_address->GetType()))));
list, 0, ThrowIfError(Dart_NewInteger(socket_address.GetType()))));
ThrowIfError(Dart_ListSetAt(
list, 1,
ThrowIfError(Dart_NewStringFromCString(socket_address->as_string()))));
ThrowIfError(Dart_NewStringFromCString(socket_address.as_string()))));
ThrowIfError(Dart_ListSetAt(
list, 2, SocketAddress::ToTypedData(socket_address->addr())));
list, 2, SocketAddress::ToTypedData(socket_address.addr())));
ThrowIfError(Dart_ListSetAt(list, 3, ThrowIfError(Dart_NewInteger(fd))));
Dart_SetReturnValue(args, list);
+14 -20
View File
@@ -183,7 +183,7 @@ class ListeningSocketRegistry {
// This function should be called from a dart runtime call in order to create
// a new (potentially shared) socket.
Dart_Handle CreateBindListen(Dart_Handle socket_object,
RawAddr addr,
const RawAddr& addr,
intptr_t backlog,
bool v6_only,
bool shared);
@@ -226,7 +226,7 @@ class ListeningSocketRegistry {
// but on different addresses.
OSSocket* next;
OSSocket(RawAddr address,
OSSocket(const RawAddr& address,
int port,
bool v6_only,
bool shared,
@@ -255,30 +255,24 @@ class ListeningSocketRegistry {
return nullptr;
}
OSSocket* FindOSSocketWithPath(OSSocket* current,
Namespace* namespc,
const char* path) {
OSSocket* FindMatchingUnixDomainSocket(OSSocket* current,
Namespace* namespc,
const RawAddr& addr) {
if (addr.is_abstract_unix_socket()) {
return FindOSSocketWithAddress(current, addr);
}
while (current != nullptr) {
ASSERT(current->address.addr.sa_family == AF_UNIX);
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
bool condition;
if (path[0] == '\0') {
condition = current->address.un.sun_path[0] == '\0' &&
strcmp(&(current->address.un.sun_path[1]), path + 1) == 0;
} else {
condition =
File::AreIdentical(current->namespc, current->address.un.sun_path,
namespc, path) == File::kIdentical;
if (current->address.is_abstract_unix_socket()) {
continue;
}
if (condition) {
return current;
}
#else
if (File::AreIdentical(current->namespc, current->address.un.sun_path,
namespc, path) == File::kIdentical) {
namespc, addr.un.sun_path) == File::kIdentical) {
return current;
}
#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
current = current->next;
}
return nullptr;
+25 -50
View File
@@ -22,7 +22,7 @@
namespace dart {
namespace bin {
int SocketAddress::GetType() {
int SocketAddress::GetType() const {
switch (addr_.ss.ss_family) {
case AF_INET6:
return TYPE_IPV6;
@@ -36,41 +36,6 @@ int SocketAddress::GetType() {
}
}
intptr_t SocketAddress::GetAddrLength(const RawAddr& addr,
bool unnamed_unix_socket) {
ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6) ||
(addr.ss.ss_family == AF_UNIX));
switch (addr.ss.ss_family) {
case AF_INET6:
return sizeof(struct sockaddr_in6);
case AF_INET:
return sizeof(struct sockaddr_in);
case AF_UNIX: {
// For an abstract UNIX socket, trailing null bytes in the name are
// meaningful. That is, the bytes '\0/tmp/dbus-xxxx' are a different name
// than '\0/tmp/dbus-xxxx\0\0\0...'. The length of the address structure
// passed to connect() etc. tells those calls how many bytes of the name
// to look at. Therefore, when computing the length of the address in
// this case, any trailing null bytes are trimmed.
// TODO(dart:io): Support abstract UNIX socket addresses that have
// trailing null bytes on purpose.
// https://github.com/dart-lang/sdk/issues/46158
intptr_t nulls = 0;
if (!unnamed_unix_socket && addr.un.sun_path[0] == '\0') {
intptr_t i = sizeof(addr.un.sun_path) - 1;
while (addr.un.sun_path[i] == '\0') {
nulls++;
i--;
}
}
return sizeof(struct sockaddr_un) - nulls;
}
default:
UNREACHABLE();
return 0;
}
}
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)
@@ -88,14 +53,13 @@ bool SocketAddress::AreAddressesEqual(const RawAddr& a, const RawAddr& b) {
sizeof(a.in6.sin6_addr)) == 0 &&
a.in6.sin6_scope_id == b.in6.sin6_scope_id;
} else if (a.ss.ss_family == AF_UNIX) {
// This is not used anywhere. The comparison of file path is done via
// File::AreIdentical().
int len = sizeof(a.un.sun_path);
for (int i = 0; i < len; i++) {
if (a.un.sun_path[i] != b.un.sun_path[i]) return false;
if (a.un.sun_path[i] == '\0') return true;
if (a.size != b.size) {
return false;
}
return true;
return (a.size <= offsetof(decltype(a.un), sun_path)) ||
(memcmp(a.un.sun_path, b.un.sun_path,
a.size - offsetof(decltype(a.un), sun_path)) == 0);
} else {
UNREACHABLE();
return false;
@@ -119,10 +83,12 @@ void SocketAddress::GetSockAddr(Dart_Handle obj, RawAddr* addr) {
memset(reinterpret_cast<void*>(addr), 0, sizeof(RawAddr));
if (len == sizeof(in_addr)) {
addr->in.sin_family = AF_INET;
addr->size = sizeof(sockaddr_in);
memmove(reinterpret_cast<void*>(&addr->in.sin_addr), data, len);
} else {
ASSERT(len == sizeof(in6_addr));
addr->in6.sin6_family = AF_INET6;
addr->size = sizeof(sockaddr_in6);
memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len);
}
Dart_TypedDataReleaseData(obj);
@@ -134,7 +100,7 @@ Dart_Handle SocketAddress::GetUnixDomainSockAddr(const char* path,
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
NamespaceScope ns(namespc, path);
path = ns.path();
bool is_abstract = (path[0] == '@');
const bool is_abstract = (path[0] == '@');
if (is_abstract) {
// The following 107 bytes after the leading null byte represents the name
// of unix domain socket. Without reseting, even users provide the same path
@@ -142,8 +108,11 @@ Dart_Handle SocketAddress::GetUnixDomainSockAddr(const char* path,
// connection will be rejected.
bzero(addr->un.sun_path, sizeof(addr->un.sun_path));
}
#else
const bool is_abstract = false;
#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
if (sizeof(path) > sizeof(addr->un.sun_path)) {
const auto path_len = strlen(path);
if (path_len >= sizeof(addr->un.sun_path)) {
OSError os_error(-1,
"The length of path exceeds the limit. "
"Check out man 7 unix page",
@@ -151,7 +120,10 @@ Dart_Handle SocketAddress::GetUnixDomainSockAddr(const char* path,
return DartUtils::NewDartOSError(&os_error);
}
addr->un.sun_family = AF_UNIX;
Utils::SNPrint(addr->un.sun_path, sizeof(addr->un.sun_path), "%s", path);
// Trailing '\0' is not meaningful for abstract namespace sockets.
const auto path_total_bytes = path_len + (is_abstract ? 0 : 1);
memmove(addr->un.sun_path, path, path_total_bytes);
addr->size = offsetof(decltype(addr->un), sun_path) + path_total_bytes;
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
// In case of abstract namespace, transfer the leading '@' into a null byte.
if (is_abstract) {
@@ -248,13 +220,15 @@ void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) {
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
ASSERT(address != nullptr);
RawAddr raw;
memset(&raw, 0, sizeof(raw));
memset(&raw.addr, 0, sizeof(raw.addr));
int type = strchr(address, ':') == nullptr ? SocketAddress::TYPE_IPV4
: SocketAddress::TYPE_IPV6;
if (type == SocketAddress::TYPE_IPV4) {
raw.addr.sa_family = AF_INET;
raw.size = sizeof(sockaddr_in);
} else {
raw.addr.sa_family = AF_INET6;
raw.size = sizeof(sockaddr_in6);
}
bool ok = SocketBase::ParseAddress(type, address, &raw);
if (!ok) {
@@ -288,8 +262,7 @@ void FUNCTION_NAME(InternetAddress_ParseScopedLinkLocalAddress)(
void FUNCTION_NAME(InternetAddress_RawAddrToString)(Dart_NativeArguments args) {
RawAddr addr;
SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 0), &addr);
// INET6_ADDRSTRLEN is larger than INET_ADDRSTRLEN
char str[INET6_ADDRSTRLEN];
char str[SocketAddress::kMaxAddressStringLength];
bool ok = SocketBase::RawAddrToString(&addr, str);
if (!ok) {
str[0] = '\0';
@@ -307,13 +280,15 @@ void FUNCTION_NAME(SocketBase_IsBindError)(Dart_NativeArguments args) {
bool SocketBase::IsValidAddress(const char* address) {
ASSERT(address != nullptr);
RawAddr raw;
memset(&raw, 0, sizeof(raw));
memset(&raw.addr, 0, sizeof(raw.addr));
int type = strchr(address, ':') == nullptr ? SocketAddress::TYPE_IPV4
: SocketAddress::TYPE_IPV6;
if (type == SocketAddress::TYPE_IPV4) {
raw.addr.sa_family = AF_INET;
raw.size = sizeof(sockaddr_in);
} else {
raw.addr.sa_family = AF_INET6;
raw.size = sizeof(sockaddr_in6);
}
return SocketBase::ParseAddress(type, address, &raw);
}
+57 -27
View File
@@ -30,12 +30,48 @@
namespace dart {
namespace bin {
union RawAddr {
struct sockaddr_in in;
struct sockaddr_in6 in6;
struct sockaddr_un un;
struct sockaddr_storage ss;
struct sockaddr addr;
struct RawAddr {
union {
sockaddr_in in;
sockaddr_in6 in6;
sockaddr_un un;
sockaddr_storage ss;
sockaddr addr;
};
socklen_t size = sizeof(sockaddr_storage);
static RawAddr FromInet4or6(const sockaddr* sa) {
RawAddr raw;
switch (sa->sa_family) {
case AF_INET:
raw.size = sizeof(sockaddr_in);
break;
case AF_INET6:
raw.size = sizeof(sockaddr_in6);
break;
default:
UNREACHABLE();
}
memmove(&raw.addr, sa, raw.size);
return raw;
}
bool is_pathname_unix_socket() const {
return ss.ss_family == AF_UNIX && !is_unnamed_unix_socket() &&
un.sun_path[0] != '\0';
}
bool is_abstract_unix_socket() const {
return ss.ss_family == AF_UNIX && !is_unnamed_unix_socket() &&
un.sun_path[0] == '\0';
}
bool is_unnamed_unix_socket() const {
// Socket is unnamed if its sockaddr contains exactly |ss.ss_family|
// and no sun_path data at all.
return ss.ss_family == AF_UNIX && size == sizeof(decltype(ss.ss_family));
}
};
class SocketAddress {
@@ -56,19 +92,15 @@ class SocketAddress {
ADDRESS_LAST = ADDRESS_ANY_IP_V6,
};
// Unix domain socket may be unnamed. In this case addr_.un.sun_path contains
// garbage and should not be inspected.
explicit SocketAddress(struct sockaddr* sa, bool unnamed_unix_socket = false);
explicit SocketAddress(const RawAddr& addr);
~SocketAddress() {}
int GetType();
int GetType() const;
const char* as_string() const { return as_string_; }
const RawAddr& addr() const { return addr_; }
static intptr_t GetAddrLength(const RawAddr& addr,
bool unnamed_unix_socket = false);
static intptr_t GetInAddrLength(const RawAddr& addr);
static bool AreAddressesEqual(const RawAddr& a, const RawAddr& b);
static void GetSockAddr(Dart_Handle obj, RawAddr* addr);
@@ -83,19 +115,17 @@ class SocketAddress {
static void SetAddrScope(RawAddr* addr, intptr_t scope_id);
static intptr_t GetAddrScope(const RawAddr& addr);
private:
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
defined(DART_HOST_OS_ANDROID)
// Unix domain address is only on Linux, Mac OS and Android now.
// unix(7) require sun_path to be 108 bytes on Linux and Android, 104 bytes on
// Mac OS.
static constexpr intptr_t kMaxUnixPathLength =
sizeof(((struct sockaddr_un*)nullptr)->sun_path);
char as_string_[kMaxUnixPathLength];
#if !defined(DART_HOST_OS_FUCHSIA)
static constexpr intptr_t kMaxAddressStringLength =
sizeof(decltype(sockaddr_un::sun_path));
#else
char as_string_[INET6_ADDRSTRLEN];
#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) ||
// defined(DART_HOST_OS_ANDROID)
static constexpr intptr_t kMaxAddressStringLength = INET6_ADDRSTRLEN;
#endif // !defined(DART_HOST_OS_FUCHSIA)
static_assert(kMaxAddressStringLength >= INET6_ADDRSTRLEN);
static_assert(kMaxAddressStringLength >= INET_ADDRSTRLEN);
private:
char as_string_[kMaxAddressStringLength];
RawAddr addr_;
DISALLOW_COPY_AND_ASSIGN(SocketAddress);
@@ -103,10 +133,10 @@ class SocketAddress {
class InterfaceSocketAddress {
public:
InterfaceSocketAddress(struct sockaddr* sa,
InterfaceSocketAddress(const RawAddr& addr,
const char* interface_name,
intptr_t interface_index)
: socket_address_(new SocketAddress(sa)),
: socket_address_(new SocketAddress(addr)),
interface_name_(interface_name),
interface_index_(interface_index) {}
@@ -228,7 +258,7 @@ class SocketBase : public AllStatic {
// to bind the socket to a specific IP.
static bool IsBindError(intptr_t error_number);
static intptr_t GetPort(intptr_t fd);
static bool GetSocketName(intptr_t fd, SocketAddress* p_sa);
static bool GetSocketName(intptr_t fd, RawAddr* raw);
static SocketAddress* GetRemotePeer(intptr_t fd, intptr_t* port);
static void GetError(intptr_t fd, OSError* os_error);
static int GetType(intptr_t fd);
+15 -32
View File
@@ -52,18 +52,15 @@
namespace dart {
namespace bin {
SocketAddress::SocketAddress(struct sockaddr* sa, bool unnamed_unix_socket) {
SocketAddress::SocketAddress(const RawAddr& addr) : addr_(addr) {
// Fuchsia does not support unix domain sockets.
if (unnamed_unix_socket) {
if (addr.is_unnamed_unix_socket()) {
FATAL("Fuchsia does not support unix domain sockets.");
}
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa),
as_string_, INET6_ADDRSTRLEN)) {
if (!SocketBase::FormatNumericAddress(addr, as_string_,
kMaxAddressStringLength)) {
as_string_[0] = 0;
}
socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa));
memmove(reinterpret_cast<void*>(&addr_), sa, salen);
}
bool SocketBase::Initialize() {
@@ -74,9 +71,8 @@ bool SocketBase::Initialize() {
bool SocketBase::FormatNumericAddress(const RawAddr& addr,
char* address,
int len) {
socklen_t salen = SocketAddress::GetAddrLength(addr);
LOG_INFO("SocketBase::FormatNumericAddress: calling getnameinfo\n");
return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len,
return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, addr.size, address, len,
nullptr, 0, NI_NUMERICHOST) == 0));
}
@@ -182,30 +178,18 @@ intptr_t SocketBase::SendMessage(intptr_t fd,
return -1;
}
bool SocketBase::GetSocketName(intptr_t fd, SocketAddress* p_sa) {
bool SocketBase::GetSocketName(intptr_t fd, RawAddr* raw) {
ASSERT(fd >= 0);
ASSERT(p_sa != nullptr);
RawAddr raw;
socklen_t size = sizeof(raw);
if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
return false;
}
// sockaddr_un contains sa_family_t sun_family and char[] sun_path.
// If size is the size of sa_family_t, this is an unnamed socket and
// sun_path contains garbage.
new (p_sa) SocketAddress(&raw.addr,
/*unnamed_unix_socket=*/size == sizeof(sa_family_t));
return true;
ASSERT(raw != nullptr);
return NO_RETRY_EXPECTED(getsockname(fd, &raw->addr, &raw->size)) == 0;
}
intptr_t SocketBase::GetPort(intptr_t fd) {
IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
ASSERT(handle->fd() >= 0);
RawAddr raw;
socklen_t size = sizeof(raw);
LOG_INFO("SocketBase::GetPort: calling getsockname(%ld)\n", handle->fd());
if (NO_RETRY_EXPECTED(getsockname(handle->fd(), &raw.addr, &size))) {
if (NO_RETRY_EXPECTED(getsockname(handle->fd(), &raw.addr, &raw.size))) {
return 0;
}
return SocketAddress::GetAddrPort(raw);
@@ -215,12 +199,11 @@ SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) {
IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
ASSERT(handle->fd() >= 0);
RawAddr raw;
socklen_t size = sizeof(raw);
if (NO_RETRY_EXPECTED(getpeername(handle->fd(), &raw.addr, &size))) {
if (NO_RETRY_EXPECTED(getpeername(handle->fd(), &raw.addr, &raw.size))) {
return nullptr;
}
*port = SocketAddress::GetAddrPort(raw);
return new SocketAddress(&raw.addr);
return new SocketAddress(raw);
}
void SocketBase::GetError(intptr_t fd, OSError* os_error) {
@@ -279,7 +262,7 @@ AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) {
if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
addresses->SetAt(i, new SocketAddress(RawAddr::FromInet4or6(c->ai_addr)));
i++;
}
}
@@ -357,9 +340,9 @@ AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
char* ifa_name = DartUtils::ScopedCopyCString(ifa->ifa_name);
addresses->SetAt(
i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name,
if_nametoindex(ifa->ifa_name)));
addresses->SetAt(i, new InterfaceSocketAddress(
RawAddr::FromInet4or6(ifa->ifa_addr), ifa_name,
if_nametoindex(ifa->ifa_name)));
i++;
}
}
+3 -3
View File
@@ -87,7 +87,7 @@ AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) {
if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
addresses->SetAt(i, new SocketAddress(RawAddr::FromInet4or6(c->ai_addr)));
i++;
}
}
@@ -125,7 +125,7 @@ bool SocketBase::JoinMulticast(intptr_t fd,
int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
struct group_req mreq;
mreq.gr_interface = interfaceIndex;
memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
memmove(&mreq.gr_group, &addr.ss, addr.size);
return NO_RETRY_EXPECTED(
setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
}
@@ -137,7 +137,7 @@ bool SocketBase::LeaveMulticast(intptr_t fd,
int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
struct group_req mreq;
mreq.gr_interface = interfaceIndex;
memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
memmove(&mreq.gr_group, &addr.ss, addr.size);
return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq,
sizeof(mreq))) == 0;
}
+1 -1
View File
@@ -78,7 +78,7 @@ AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) {
if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
addresses->SetAt(i, new SocketAddress(RawAddr::FromInet4or6(c->ai_addr)));
i++;
}
}
+21 -50
View File
@@ -25,23 +25,18 @@
namespace dart {
namespace bin {
SocketAddress::SocketAddress(struct sockaddr* sa, bool unnamed_unix_socket) {
if (unnamed_unix_socket) {
SocketAddress::SocketAddress(const RawAddr& addr) : addr_(addr) {
if (addr.is_unnamed_unix_socket()) {
// This is an unnamed unix domain socket.
as_string_[0] = 0;
} else if (sa->sa_family == AF_UNIX) {
struct sockaddr_un* un = ((struct sockaddr_un*)sa);
memmove(as_string_, un->sun_path, sizeof(un->sun_path));
} else if (addr.ss.ss_family == AF_UNIX) {
memmove(as_string_, addr.un.sun_path, sizeof(addr.un.sun_path));
} else {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa),
as_string_, INET6_ADDRSTRLEN)) {
if (!SocketBase::FormatNumericAddress(addr, as_string_,
kMaxAddressStringLength)) {
as_string_[0] = 0;
}
}
socklen_t salen =
GetAddrLength(*reinterpret_cast<RawAddr*>(sa), unnamed_unix_socket);
memmove(reinterpret_cast<void*>(&addr_), sa, salen);
}
bool SocketBase::Initialize() {
@@ -52,8 +47,7 @@ bool SocketBase::Initialize() {
bool SocketBase::FormatNumericAddress(const RawAddr& addr,
char* address,
int len) {
socklen_t salen = SocketAddress::GetAddrLength(addr);
return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len,
return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, addr.size, address, len,
nullptr, 0, NI_NUMERICHOST)) == 0);
}
@@ -87,9 +81,8 @@ intptr_t SocketBase::RecvFrom(intptr_t fd,
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));
recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr->size));
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.
@@ -206,9 +199,8 @@ intptr_t SocketBase::SendTo(intptr_t fd,
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)));
ssize_t written_bytes = TEMP_FAILURE_RETRY(
sendto(fd, buffer, num_bytes, 0, &addr.addr, addr.size));
ASSERT(EAGAIN == EWOULDBLOCK);
if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
@@ -279,28 +271,16 @@ intptr_t SocketBase::SendMessage(intptr_t fd,
return written_bytes;
}
bool SocketBase::GetSocketName(intptr_t fd, SocketAddress* p_sa) {
bool SocketBase::GetSocketName(intptr_t fd, RawAddr* raw) {
ASSERT(fd >= 0);
ASSERT(p_sa != nullptr);
RawAddr raw;
socklen_t size = sizeof(raw);
if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
return false;
}
// sockaddr_un contains sa_family_t sun_family and char[] sun_path.
// If size is the size of sa_family_t, this is an unnamed socket and
// sun_path contains garbage.
new (p_sa) SocketAddress(&raw.addr,
/*unnamed_unix_socket=*/size == sizeof(sa_family_t));
return true;
ASSERT(raw != nullptr);
return NO_RETRY_EXPECTED(getsockname(fd, &raw->addr, &raw->size)) == 0;
}
intptr_t SocketBase::GetPort(intptr_t fd) {
ASSERT(fd >= 0);
RawAddr raw;
socklen_t size = sizeof(raw);
if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &raw.size))) {
return 0;
}
return SocketAddress::GetAddrPort(raw);
@@ -309,19 +289,11 @@ intptr_t SocketBase::GetPort(intptr_t fd) {
SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) {
ASSERT(fd >= 0);
RawAddr raw;
socklen_t size = sizeof(raw);
if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) {
if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &raw.size))) {
return nullptr;
}
// sockaddr_un contains sa_family_t sun_family and char[] sun_path.
// If size is the size of sa_family_t, this is an unnamed socket and
// sun_path contains garbage.
if (size == sizeof(sa_family_t)) {
*port = 0;
return new SocketAddress(&raw.addr, /*unnamed_unix_socket=*/true);
}
*port = SocketAddress::GetAddrPort(raw);
return new SocketAddress(&raw.addr);
return new SocketAddress(raw);
}
intptr_t SocketBase::GetStdioHandle(intptr_t num) {
@@ -333,9 +305,8 @@ bool SocketBase::ReverseLookup(const RawAddr& addr,
intptr_t host_len,
OSError** os_error) {
ASSERT(host_len >= NI_MAXHOST);
int status = NO_RETRY_EXPECTED(
getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host,
host_len, nullptr, 0, NI_NAMEREQD));
int status = NO_RETRY_EXPECTED(getnameinfo(
&addr.addr, addr.size, host, host_len, nullptr, 0, NI_NAMEREQD));
if (status != 0) {
ASSERT(*os_error == nullptr);
*os_error =
@@ -396,9 +367,9 @@ AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
char* ifa_name = DartUtils::ScopedCopyCString(ifa->ifa_name);
addresses->SetAt(
i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name,
if_nametoindex(ifa->ifa_name)));
addresses->SetAt(i, new InterfaceSocketAddress(
RawAddr::FromInet4or6(ifa->ifa_addr), ifa_name,
if_nametoindex(ifa->ifa_name)));
i++;
}
}
+45 -61
View File
@@ -20,23 +20,19 @@
namespace dart {
namespace bin {
SocketAddress::SocketAddress(struct sockaddr* sockaddr,
bool unnamed_unix_socket) {
// Unix domain sockets not supported on Win. Remove this assert if enabled.
ASSERT(!unnamed_unix_socket);
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
// Clear the port before calling WSAAddressToString as WSAAddressToString
// includes the port in the formatted string.
int err =
SocketBase::FormatNumericAddress(*raw, as_string_, INET6_ADDRSTRLEN);
if (err != 0) {
SocketAddress::SocketAddress(const RawAddr& addr) : addr_(addr) {
if (addr.is_unnamed_unix_socket()) {
as_string_[0] = 0;
} else if (addr.ss.ss_family == AF_UNIX) {
memmove(as_string_, addr.un.sun_path, sizeof(addr.un.sun_path));
} else {
int err = SocketBase::FormatNumericAddress(addr, as_string_,
kMaxAddressStringLength);
if (err != 0) {
as_string_[0] = 0;
}
}
memmove(reinterpret_cast<void*>(&addr_), sockaddr,
SocketAddress::GetAddrLength(*raw));
}
static Mutex* init_mutex = new Mutex();
@@ -62,18 +58,16 @@ bool SocketBase::Initialize() {
bool SocketBase::FormatNumericAddress(const RawAddr& addr,
char* address,
int len) {
socklen_t salen = SocketAddress::GetAddrLength(addr);
DWORD l = len;
RawAddr& raw = const_cast<RawAddr&>(addr);
wchar_t* waddress = reinterpret_cast<wchar_t*>(
Dart_ScopeAllocate((salen + 1) * sizeof(wchar_t)));
wchar_t buf[SocketAddress::kMaxAddressStringLength];
DWORD result_len = ARRAY_SIZE(buf);
intptr_t result =
WSAAddressToStringW(&raw.addr, salen, nullptr, waddress, &l);
WSAAddressToStringW(&raw.addr, raw.size, nullptr, buf, &result_len);
if (result != 0) {
return true;
}
WideToUtf8Scope wide_name(waddress);
strncpy(address, wide_name.utf8(), l);
WideToUtf8Scope wide_name(buf);
strncpy(address, wide_name.utf8(), len);
return false;
}
@@ -96,8 +90,7 @@ intptr_t SocketBase::RecvFrom(intptr_t fd,
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);
return handle->RecvFrom(buffer, num_bytes, addr);
}
bool SocketControlMessage::is_file_descriptors_control_message() {
@@ -141,8 +134,7 @@ intptr_t SocketBase::SendTo(intptr_t fd,
SocketOpKind sync) {
Handle* handle = reinterpret_cast<Handle*>(fd);
RawAddr& raw = const_cast<RawAddr&>(addr);
return handle->SendTo(buffer, num_bytes, &raw.addr,
SocketAddress::GetAddrLength(addr));
return handle->SendTo(buffer, num_bytes, raw);
}
intptr_t SocketBase::SendMessage(intptr_t fd,
@@ -156,29 +148,18 @@ intptr_t SocketBase::SendMessage(intptr_t fd,
return -1;
}
bool SocketBase::GetSocketName(intptr_t fd, SocketAddress* p_sa) {
bool SocketBase::GetSocketName(intptr_t fd, RawAddr* raw) {
ASSERT(fd >= 0);
ASSERT(p_sa != nullptr);
RawAddr raw;
socklen_t size = sizeof(raw);
if (getsockname(fd, &raw.addr, &size) == SOCKET_ERROR) {
return false;
}
// sockaddr_un contains sa_family_t sun_family and char[] sun_path.
// If size is the size of sa_family_t, this is an unnamed socket and
// sun_path contains garbage.
new (p_sa) SocketAddress(&raw.addr,
/*unnamed_unix_socket=*/size == sizeof(u_short));
return true;
ASSERT(raw != nullptr);
return getsockname(fd, &raw->addr, &raw->size) != SOCKET_ERROR;
}
intptr_t SocketBase::GetPort(intptr_t fd) {
ASSERT(reinterpret_cast<Handle*>(fd)->is_socket());
SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
RawAddr raw;
socklen_t size = sizeof(raw);
if (getsockname(socket_handle->socket(), &raw.addr, &size) == SOCKET_ERROR) {
if (getsockname(socket_handle->socket(), &raw.addr, &raw.size) ==
SOCKET_ERROR) {
return 0;
}
return SocketAddress::GetAddrPort(raw);
@@ -192,16 +173,17 @@ SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) {
reinterpret_cast<ClientSocket*>(fd)->PopulateRemoteAddr(raw)) {
// `raw` was populated by `ClientSocket::PopulateRemoteAddr`.
} else {
socklen_t size = sizeof(raw);
if (getpeername(socket_handle->socket(), &raw.addr, &size)) {
if (getpeername(socket_handle->socket(), &raw.addr, &raw.size)) {
return nullptr;
}
}
*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);
if (raw.ss.ss_family != AF_UNIX) {
SocketAddress::SetAddrPort(&raw, 0);
}
return new SocketAddress(raw);
}
bool SocketBase::IsBindError(intptr_t error_number) {
@@ -278,7 +260,11 @@ AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
intptr_t i = 0;
for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) {
if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
RawAddr raw;
memmove(&raw.addr, c->ai_addr, c->ai_addrlen);
raw.size = c->ai_addrlen;
addresses->SetAt(i, new SocketAddress(raw));
i++;
}
}
@@ -291,8 +277,8 @@ bool SocketBase::ReverseLookup(const RawAddr& addr,
intptr_t host_len,
OSError** os_error) {
ASSERT(host_len >= NI_MAXHOST);
int status = getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host,
host_len, nullptr, 0, NI_NAMEREQD);
int status = getnameinfo(&addr.addr, addr.size, host, host_len, nullptr, 0,
NI_NAMEREQD);
if (status != 0) {
ASSERT(*os_error == nullptr);
DWORD error_code = WSAGetLastError();
@@ -316,25 +302,23 @@ bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) {
}
bool SocketBase::RawAddrToString(RawAddr* addr, char* str) {
// According to InetNtopW(), buffer should be large enough for at least 46
// characters for IPv6 and 16 for IPv4.
COMPILE_ASSERT(INET6_ADDRSTRLEN >= 46);
wchar_t tmp_buffer[INET6_ADDRSTRLEN];
wchar_t tmp_buffer[SocketAddress::kMaxAddressStringLength];
if (addr->addr.sa_family == AF_INET) {
if (InetNtop(AF_INET, &addr->in.sin_addr, tmp_buffer, INET_ADDRSTRLEN) ==
nullptr) {
if (InetNtop(AF_INET, &addr->in.sin_addr, tmp_buffer,
ARRAY_SIZE(tmp_buffer)) == nullptr) {
return false;
}
} else {
ASSERT(addr->addr.sa_family == AF_INET6);
if (InetNtop(AF_INET6, &addr->in6.sin6_addr, tmp_buffer,
INET6_ADDRSTRLEN) == nullptr) {
ARRAY_SIZE(tmp_buffer)) == nullptr) {
return false;
}
}
WideToUtf8Scope wide_to_utf8_scope(tmp_buffer);
if (wide_to_utf8_scope.length() <= INET6_ADDRSTRLEN) {
strncpy(str, wide_to_utf8_scope.utf8(), INET6_ADDRSTRLEN);
if (wide_to_utf8_scope.length() < SocketAddress::kMaxAddressStringLength) {
strncpy(str, wide_to_utf8_scope.utf8(),
SocketAddress::kMaxAddressStringLength);
return true;
}
return false;
@@ -385,7 +369,7 @@ AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
!(a->Flags & IP_ADAPTER_IPV6_ENABLED));
addresses->SetAt(i,
new InterfaceSocketAddress(
u->Address.lpSockaddr,
RawAddr::FromInet4or6(u->Address.lpSockaddr),
StringUtilsWin::WideToUtf8(a->FriendlyName),
a->Ipv6IfIndex != 0 ? a->Ipv6IfIndex : a->IfIndex));
i++;
@@ -521,7 +505,7 @@ bool SocketBase::JoinMulticast(intptr_t fd,
int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
struct group_req mreq;
mreq.gr_interface = interfaceIndex;
memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
memmove(&mreq.gr_group, &addr.ss, addr.size);
return setsockopt(handle->socket(), proto, MCAST_JOIN_GROUP,
reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0;
}
@@ -534,7 +518,7 @@ bool SocketBase::LeaveMulticast(intptr_t fd,
int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
struct group_req mreq;
mreq.gr_interface = interfaceIndex;
memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
memmove(&mreq.gr_group, &addr.ss, addr.size);
return setsockopt(handle->socket(), proto, MCAST_LEAVE_GROUP,
reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0;
}
+5 -7
View File
@@ -82,8 +82,8 @@ static intptr_t Create(const RawAddr& addr) {
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
LOG_INFO("Connect: calling connect(%ld)\n", handle->fd());
intptr_t result = NO_RETRY_EXPECTED(
connect(handle->fd(), &addr.addr, SocketAddress::GetAddrLength(addr)));
intptr_t result =
NO_RETRY_EXPECTED(connect(handle->fd(), &addr.addr, addr.size));
if ((result == 0) || (errno == EINPROGRESS)) {
return reinterpret_cast<intptr_t>(handle);
}
@@ -166,8 +166,7 @@ intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
}
LOG_INFO("ServerSocket::CreateBindListen: calling bind(%ld)\n", fd);
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
if (NO_RETRY_EXPECTED(bind(fd, &addr.addr, addr.size)) < 0) {
LOG_ERR("ServerSocket::CreateBindListen: bind(%ld) failed\n", fd);
FDUtils::SaveErrorAndClose(fd);
return -1;
@@ -229,10 +228,9 @@ static bool IsTemporaryAcceptError(int error) {
intptr_t ServerSocket::Accept(intptr_t fd) {
IOHandle* listen_handle = reinterpret_cast<IOHandle*>(fd);
intptr_t socket;
struct sockaddr clientaddr;
socklen_t addrlen = sizeof(clientaddr);
RawAddr client_addr;
LOG_INFO("ServerSocket::Accept: calling accept(%ld)\n", fd);
socket = listen_handle->Accept(&clientaddr, &addrlen);
socket = listen_handle->Accept(&client_addr);
if (socket == -1) {
if (IsTemporaryAcceptError(errno)) {
// We need to signal to the caller that this is actually not an
+13 -20
View File
@@ -43,8 +43,7 @@ static intptr_t Create(const RawAddr& addr) {
}
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
intptr_t result = TEMP_FAILURE_RETRY(connect(fd, &addr.addr, addr.size));
if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
@@ -65,8 +64,7 @@ intptr_t Socket::CreateUnixDomainConnect(const RawAddr& addr) {
if (fd < 0) {
return fd;
}
intptr_t result = TEMP_FAILURE_RETRY(connect(
fd, (struct sockaddr*)&addr.un, SocketAddress::GetAddrLength(addr)));
intptr_t result = TEMP_FAILURE_RETRY(connect(fd, &addr.addr, addr.size));
if (result == 0 || errno == EAGAIN) {
return fd;
}
@@ -85,8 +83,8 @@ intptr_t Socket::CreateBindConnect(const RawAddr& addr,
VOID_NO_RETRY_EXPECTED(
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
intptr_t result =
TEMP_FAILURE_RETRY(bind(fd, &source_addr.addr, source_addr.size));
if (result != 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
@@ -102,15 +100,14 @@ intptr_t Socket::CreateUnixDomainBindConnect(const RawAddr& addr,
return fd;
}
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
intptr_t result =
TEMP_FAILURE_RETRY(bind(fd, &source_addr.addr, source_addr.size));
if (result != 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
}
result = TEMP_FAILURE_RETRY(connect(fd, (struct sockaddr*)&addr.un,
SocketAddress::GetAddrLength(addr)));
result = TEMP_FAILURE_RETRY(connect(fd, &addr.addr, addr.size));
if (result == 0 || errno == EAGAIN) {
return fd;
}
@@ -170,8 +167,7 @@ intptr_t Socket::CreateBindDatagram(const RawAddr& addr,
return -1;
}
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
if (NO_RETRY_EXPECTED(bind(fd, &addr.addr, addr.size)) < 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -199,8 +195,7 @@ intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
}
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
if (NO_RETRY_EXPECTED(bind(fd, &addr.addr, addr.size)) < 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -226,8 +221,7 @@ intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
intptr_t ServerSocket::CreateUnixDomainBindListen(const RawAddr& addr,
intptr_t backlog) {
intptr_t fd = Create(addr);
if (NO_RETRY_EXPECTED(bind(fd, (struct sockaddr*)&addr.un,
SocketAddress::GetAddrLength(addr))) < 0) {
if (NO_RETRY_EXPECTED(bind(fd, &addr.addr, addr.size)) < 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -254,10 +248,9 @@ static bool IsTemporaryAcceptError(int error) {
intptr_t ServerSocket::Accept(intptr_t fd) {
intptr_t socket;
struct sockaddr clientaddr;
socklen_t addrlen = sizeof(clientaddr);
socket = TEMP_FAILURE_RETRY(
accept4(fd, &clientaddr, &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC));
RawAddr client_addr;
socket = TEMP_FAILURE_RETRY(accept4(fd, &client_addr.addr, &client_addr.size,
SOCK_NONBLOCK | SOCK_CLOEXEC));
if (socket == -1) {
if (IsTemporaryAcceptError(errno)) {
// We need to signal to the caller that this is actually not an
+10 -15
View File
@@ -53,8 +53,7 @@ static intptr_t Create(const RawAddr& addr) {
}
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
intptr_t result = TEMP_FAILURE_RETRY(connect(fd, &addr.addr, addr.size));
if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
@@ -90,8 +89,8 @@ intptr_t Socket::CreateBindConnect(const RawAddr& addr,
VOID_NO_RETRY_EXPECTED(
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
intptr_t result =
TEMP_FAILURE_RETRY(bind(fd, &source_addr.addr, source_addr.size));
if (result != 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
@@ -107,8 +106,8 @@ intptr_t Socket::CreateUnixDomainBindConnect(const RawAddr& addr,
return fd;
}
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
intptr_t result =
TEMP_FAILURE_RETRY(bind(fd, &source_addr.addr, source_addr.size));
if (result != 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
@@ -160,8 +159,7 @@ intptr_t Socket::CreateBindDatagram(const RawAddr& addr,
VOID_NO_RETRY_EXPECTED(
setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)));
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
if (NO_RETRY_EXPECTED(bind(fd, &addr.addr, addr.size)) < 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -204,8 +202,7 @@ intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
}
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
if (NO_RETRY_EXPECTED(bind(fd, &addr.addr, addr.size)) < 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -245,8 +242,7 @@ intptr_t ServerSocket::CreateUnixDomainBindListen(const RawAddr& addr,
return -1;
}
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
if (NO_RETRY_EXPECTED(bind(fd, &addr.addr, addr.size)) < 0) {
FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -270,9 +266,8 @@ bool ServerSocket::StartAccept(intptr_t fd) {
intptr_t ServerSocket::Accept(intptr_t fd) {
intptr_t socket;
struct sockaddr clientaddr;
socklen_t addrlen = sizeof(clientaddr);
socket = TEMP_FAILURE_RETRY(accept(fd, &clientaddr, &addrlen));
RawAddr client_addr;
socket = TEMP_FAILURE_RETRY(accept(fd, &client_addr.addr, &client_addr.size));
if (socket == -1) {
if (errno == EAGAIN) {
// We need to signal to the caller that this is actually not an
+51 -42
View File
@@ -68,8 +68,10 @@ static intptr_t Connect(intptr_t fd,
ClientSocket* handle = reinterpret_cast<ClientSocket*>(fd);
SOCKET s = handle->socket();
int status =
bind(s, &bind_addr.addr, SocketAddress::GetAddrLength(bind_addr));
// Note: unlike |connect| |ConnectEx| requires *bound* socket, so we must
// manually bind() it to some local address before we can issue a connect
// request to the remote address.
int status = bind(s, &bind_addr.addr, bind_addr.size);
if (status != NO_ERROR) {
const int rc = WSAGetLastError();
handle->mark_closed(); // Destructor asserts that socket is marked closed.
@@ -80,9 +82,9 @@ static intptr_t Connect(intptr_t fd,
}
auto buffer = OverlappedBuffer::AllocateConnectBuffer(handle);
status = EventHandler::delegate()->connect_ex()(
s, &addr.addr, SocketAddress::GetAddrLength(addr), nullptr, 0, nullptr,
buffer->GetCleanOverlapped());
status = EventHandler::delegate()->connect_ex()(s, &addr.addr, addr.size,
nullptr, 0, nullptr,
buffer->GetCleanOverlapped());
if (status == TRUE) {
handle->ConnectComplete();
return fd;
@@ -90,6 +92,7 @@ static intptr_t Connect(intptr_t fd,
buffer.release(); // Ownership passed to event handler.
return fd;
}
const int rc = WSAGetLastError();
// Cleanup in case of error.
handle->Close();
@@ -109,18 +112,23 @@ intptr_t Socket::CreateConnect(const RawAddr& addr) {
bind_addr.ss.ss_family = addr.ss.ss_family;
if (addr.ss.ss_family == AF_INET) {
bind_addr.in.sin_addr.s_addr = INADDR_ANY;
} else {
bind_addr.size = sizeof(sockaddr_in);
} else if (addr.ss.ss_family == AF_INET6) {
bind_addr.in6.sin6_addr = in6addr_any;
bind_addr.size = sizeof(sockaddr_in6);
} else if (addr.ss.ss_family == AF_UNIX) {
// Local address is an anonymous unix socket.
bind_addr.size = sizeof(ADDRESS_FAMILY);
} else {
SetLastError(ERROR_NOT_SUPPORTED);
return -1;
}
return Connect(fd, addr, bind_addr);
}
intptr_t Socket::CreateUnixDomainConnect(const RawAddr& addr) {
// TODO(21403): Support unix domain socket on Windows
// https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
SetLastError(ERROR_NOT_SUPPORTED);
return -1;
return CreateConnect(addr);
}
intptr_t Socket::CreateBindConnect(const RawAddr& addr,
@@ -135,8 +143,7 @@ intptr_t Socket::CreateBindConnect(const RawAddr& addr,
intptr_t Socket::CreateUnixDomainBindConnect(const RawAddr& addr,
const RawAddr& source_addr) {
SetLastError(ERROR_NOT_SUPPORTED);
return -1;
return CreateBindConnect(addr, source_addr);
}
intptr_t ServerSocket::Accept(intptr_t fd) {
@@ -200,7 +207,7 @@ intptr_t Socket::CreateBindDatagram(const RawAddr& addr,
return -1;
}
status = bind(s, &addr.addr, SocketAddress::GetAddrLength(addr));
status = bind(s, &addr.addr, addr.size);
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
closesocket(s);
@@ -215,29 +222,32 @@ intptr_t Socket::CreateBindDatagram(const RawAddr& addr,
intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
intptr_t backlog,
bool v6_only) {
SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, IPPROTO_TCP);
SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM,
addr.ss.ss_family == AF_UNIX ? 0 : IPPROTO_TCP);
if (s == INVALID_SOCKET) {
return -1;
}
BOOL optval = true;
int status =
setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
reinterpret_cast<const char*>(&optval), sizeof(optval));
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
closesocket(s);
SetLastError(rc);
return -1;
int status;
if (addr.ss.ss_family != AF_UNIX) {
BOOL optval = true;
status = setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
reinterpret_cast<const char*>(&optval), sizeof(optval));
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
closesocket(s);
SetLastError(rc);
return -1;
}
}
if (addr.ss.ss_family == AF_INET6) {
optval = v6_only;
BOOL optval = v6_only;
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
reinterpret_cast<const char*>(&optval), sizeof(optval));
}
status = bind(s, &addr.addr, SocketAddress::GetAddrLength(addr));
status = bind(s, &addr.addr, addr.size);
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
closesocket(s);
@@ -245,20 +255,22 @@ intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
return -1;
}
ListenSocket* listen_socket = new ListenSocket(s);
ListenSocket* listen_socket = new ListenSocket(s, addr.ss.ss_family);
// Test for invalid socket port 65535 (some browsers disallow it).
if ((SocketAddress::GetAddrPort(addr) == 0) &&
(SocketBase::GetPort(reinterpret_cast<intptr_t>(listen_socket)) ==
65535)) {
// Don't close fd until we have created new. By doing that we ensure another
// port.
intptr_t new_s = CreateBindListen(addr, backlog, v6_only);
DWORD rc = WSAGetLastError();
closesocket(s);
listen_socket->Release();
SetLastError(rc);
return new_s;
if (addr.ss.ss_family != AF_UNIX) {
// Test for invalid socket port 65535 (some browsers disallow it).
if ((SocketAddress::GetAddrPort(addr) == 0) &&
(SocketBase::GetPort(reinterpret_cast<intptr_t>(listen_socket)) ==
65535)) {
// Don't close fd until we have created new. By doing that we ensure
// another port.
intptr_t new_s = CreateBindListen(addr, backlog, v6_only);
DWORD rc = WSAGetLastError();
closesocket(s);
listen_socket->Release();
SetLastError(rc);
return new_s;
}
}
status = listen(s, backlog > 0 ? backlog : SOMAXCONN);
@@ -275,10 +287,7 @@ intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
intptr_t ServerSocket::CreateUnixDomainBindListen(const RawAddr& addr,
intptr_t backlog) {
// TODO(21403): Support unix domain socket on Windows
// https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
SetLastError(ERROR_NOT_SUPPORTED);
return -1;
return CreateBindListen(addr, backlog);
}
bool ServerSocket::StartAccept(intptr_t fd) {
+2 -2
View File
@@ -84,7 +84,7 @@ void FUNCTION_NAME(SynchronousSocket_LookupRequest)(Dart_NativeArguments args) {
error = Dart_ListSetAt(entry, 1, as_string);
DART_CHECK_ERROR_AND_CLEANUP(error, addresses);
RawAddr raw = addr->addr();
const auto& raw = addr->addr();
Dart_Handle data = SocketAddress::ToTypedData(raw);
DART_CHECK_ERROR_AND_CLEANUP(data, addresses);
@@ -301,7 +301,7 @@ void FUNCTION_NAME(SynchronousSocket_GetRemotePeer)(Dart_NativeArguments args) {
Dart_ListSetAt(entry, 1, Dart_NewStringFromCString(addr->as_string()));
DART_CHECK_ERROR_AND_CLEANUP(error, addr);
RawAddr raw = addr->addr();
const auto& raw = addr->addr();
error = Dart_ListSetAt(entry, 2, SocketAddress::ToTypedData(raw));
DART_CHECK_ERROR_AND_CLEANUP(error, addr);
+1 -2
View File
@@ -32,8 +32,7 @@ static intptr_t Create(const RawAddr& addr) {
}
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
intptr_t result = TEMP_FAILURE_RETRY(connect(fd, &addr.addr, addr.size));
if (result == 0) {
return fd;
}
+1 -2
View File
@@ -32,8 +32,7 @@ static intptr_t Create(const RawAddr& addr) {
}
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
intptr_t result = TEMP_FAILURE_RETRY(connect(fd, &addr.addr, addr.size));
if (result == 0) {
return fd;
}
+1 -2
View File
@@ -35,8 +35,7 @@ static intptr_t Create(const RawAddr& addr) {
}
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
intptr_t result = TEMP_FAILURE_RETRY(connect(fd, &addr.addr, addr.size));
if (result == 0) {
return fd;
}
+4 -7
View File
@@ -23,8 +23,7 @@ static intptr_t Create(const RawAddr& addr) {
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));
intptr_t result = connect(socket, &addr.addr, addr.size);
return (result == SOCKET_ERROR) ? -1 : socket;
}
@@ -43,8 +42,7 @@ intptr_t SynchronousSocket::Available(intptr_t fd) {
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) {
if (getsockname(socket, &raw.addr, &raw.size) == SOCKET_ERROR) {
return 0;
}
return SocketAddress::GetAddrPort(raw);
@@ -53,15 +51,14 @@ intptr_t SynchronousSocket::GetPort(intptr_t fd) {
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)) {
if (getpeername(socket, &raw.addr, &raw.size)) {
return nullptr;
}
*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);
return new SocketAddress(raw);
}
intptr_t SynchronousSocket::Read(intptr_t fd,
+97 -55
View File
@@ -7,11 +7,15 @@ import 'dart:convert';
import 'dart:io';
import 'package:expect/expect.dart';
import 'package:path/path.dart' as p;
import 'test_utils.dart' show withTempDir;
Future testAddress(String name) async {
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
var server = await ServerSocket.bind(address, 0);
var client = await Socket.connect(address, server.port);
@@ -34,7 +38,10 @@ Future testAddress(String name) async {
}
testBindShared(String name) async {
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
var socket = await ServerSocket.bind(address, 0, shared: true);
Expect.isTrue(socket.port == 0);
@@ -46,7 +53,7 @@ testBindShared(String name) async {
// Test relative path
var path = name.substring(name.lastIndexOf('/') + 1);
address = InternetAddress(
'${name}/../${path}/sock',
p.join(name, '..', path, 'sock'),
type: InternetAddressType.unix,
);
@@ -63,8 +70,11 @@ testBindShared(String name) async {
await socket3.close();
}
testBind(String name) async {
final address = InternetAddress('$name/sock', type: InternetAddressType.unix);
Future<void> testBind(String name) async {
final address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
final server = await ServerSocket.bind(address, 0, shared: false);
Expect.isTrue(server.address.toString().contains(name));
// Unix domain socket does not have a valid port number.
@@ -87,7 +97,10 @@ testBind(String name) async {
}
Future testListenCloseListenClose(String name) async {
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
ServerSocket socket = await ServerSocket.bind(address, 0, shared: true);
ServerSocket socket2 = await ServerSocket.bind(
address,
@@ -124,12 +137,15 @@ Future testListenCloseListenClose(String name) async {
}
Future testSourceAddressConnect(String name) async {
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
ServerSocket server = await ServerSocket.bind(address, 0);
var completer = Completer<void>();
var localAddress = InternetAddress(
'$name/local',
p.join(name, 'local'),
type: InternetAddressType.unix,
);
server.listen((Socket socket) async {
@@ -267,7 +283,10 @@ Future testExistingFile(String name) async {
// Test that a leftover file(In case of previous process being killed and
// finalizer doesn't clean up the file) will be cleaned up and bind() should
// be able to bind to the socket.
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
// Create a file with the same name
File(address.address).createSync();
try {
@@ -280,8 +299,19 @@ Future testExistingFile(String name) async {
Expect.fail("bind should fail with existing file");
}
bool isUnsupportedOperationError(e) {
final msg = e.toString();
return e is OSError &&
(msg.contains('Operation not supported') ||
msg.contains('unsupported option') ||
msg.contains('Protocol not available'));
}
Future testSetSockOpt(String name) async {
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
var server = await ServerSocket.bind(address, 0, shared: false);
var sub;
@@ -303,7 +333,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.getRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -316,7 +346,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.getRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -329,7 +359,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.getRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -342,7 +372,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.getRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -355,7 +385,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.getRawOption(option);
} catch (e) {
Expect.contains('Protocol not available', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -368,7 +398,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.getRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -381,7 +411,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.getRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -389,7 +419,7 @@ Future testSetSockOpt(String name) async {
try {
socket.setOption(SocketOption.tcpNoDelay, true);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
for (int i = 0; i < 5; i++) {
@@ -401,7 +431,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.setRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -414,7 +444,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.setRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -427,7 +457,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.setRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -440,7 +470,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.setRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -453,7 +483,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.setRawOption(option);
} catch (e) {
Expect.contains('Protocol not available', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -466,7 +496,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.setRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -479,7 +509,7 @@ Future testSetSockOpt(String name) async {
);
var result = socket.setRawOption(option);
} catch (e) {
Expect.contains('Operation not supported', e.toString());
Expect.isTrue(isUnsupportedOperationError(e));
}
}
@@ -488,7 +518,10 @@ Future testSetSockOpt(String name) async {
}
Future testHttpServer(String name) async {
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var address = InternetAddress(
p.join(name, 'sock'),
type: InternetAddressType.unix,
);
var httpServer = await HttpServer.bind(address, 0);
var sub;
@@ -512,7 +545,7 @@ Future testFileMessage(String tempDirPath) async {
final completer = Completer<bool>();
final address = InternetAddress(
'$tempDirPath/sock',
p.join(tempDirPath, 'sock'),
type: InternetAddressType.unix,
);
final server = await RawServerSocket.bind(address, 0, shared: false);
@@ -553,7 +586,7 @@ Future testFileMessage(String tempDirPath) async {
});
});
final file = File('$tempDirPath/myfile.txt');
final file = File(p.join(tempDirPath, 'myfile.txt'));
final randomAccessFile = file.openSync(mode: FileMode.write);
// Send a message with sample file.
final socket = await RawSocket.connect(address, 0);
@@ -593,7 +626,7 @@ Future testTooLargeControlMessage(String tempDirPath) async {
}
final completer = Completer<bool>();
final address = InternetAddress(
'$tempDirPath/sock',
p.join(tempDirPath, 'sock'),
type: InternetAddressType.unix,
);
final server = await RawServerSocket.bind(address, 0, shared: false);
@@ -610,7 +643,7 @@ Future testTooLargeControlMessage(String tempDirPath) async {
});
});
final file = File('$tempDirPath/myfile.txt');
final file = File(p.join(tempDirPath, 'myfile.txt'));
final randomAccessFile = file.openSync(mode: FileMode.write);
// Send a message with sample file.
final socket = await RawSocket.connect(address, 0);
@@ -649,7 +682,7 @@ Future testFileMessageWithShortRead(String tempDirPath) async {
final completer = Completer<bool>();
final address = InternetAddress(
'$tempDirPath/sock',
p.join(tempDirPath, 'sock'),
type: InternetAddressType.unix,
);
final server = await RawServerSocket.bind(address, 0, shared: false);
@@ -694,7 +727,7 @@ Future testFileMessageWithShortRead(String tempDirPath) async {
});
});
final file = File('$tempDirPath/myfile.txt');
final file = File(p.join(tempDirPath, 'myfile.txt'));
final randomAccessFile = file.openSync(mode: FileMode.write);
// Send a message with sample file.
final socket = await RawSocket.connect(address, 0);
@@ -765,7 +798,7 @@ Future testSocketMessage(String uniqueName) async {
return;
}
final address = InternetAddress(
'$uniqueName/sock',
p.join(uniqueName, 'sock'),
type: InternetAddressType.unix,
);
final server = await RawServerSocket.bind(address, 0, shared: false);
@@ -876,7 +909,7 @@ Future testStdioMessage(String tempDirPath, {bool caller = false}) async {
}
final address = InternetAddress(
'$tempDirPath/sock',
p.join(tempDirPath, 'sock'),
type: InternetAddressType.unix,
);
final server = await RawServerSocket.bind(address, 0, shared: false);
@@ -909,7 +942,7 @@ Future testStdioMessage(String tempDirPath, {bool caller = false}) async {
});
});
final file = File('$tempDirPath/myfile.txt');
final file = File(p.join(tempDirPath, 'myfile.txt'));
final randomAccessFile = file.openSync(mode: FileMode.write);
// Send a message with sample file.
var socket = await RawSocket.connect(address, 0);
@@ -940,7 +973,7 @@ Future testReadPipeMessage(String uniqueName) async {
return;
}
final address = InternetAddress(
'$uniqueName/sock',
p.join(uniqueName, 'sock'),
type: InternetAddressType.unix,
);
final server = await RawServerSocket.bind(address, 0, shared: false);
@@ -1011,7 +1044,7 @@ Future testWritePipeMessage(String uniqueName) async {
return;
}
final address = InternetAddress(
'$uniqueName/sock',
p.join(uniqueName, 'sock'),
type: InternetAddressType.unix,
);
final server = await RawServerSocket.bind(address, 0, shared: false);
@@ -1080,26 +1113,32 @@ Future testWritePipeMessage(String uniqueName) async {
}
Future testDeleteFile(String tempDirPath) async {
if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
return;
}
final name = '$tempDirPath/sock';
final name = p.join(tempDirPath, 'sock');
final address = InternetAddress(name, type: InternetAddressType.unix);
var server = await RawServerSocket.bind(address, 0, shared: false);
final file = File(name);
Expect.isTrue(file.existsSync());
Expect.isTrue(await file.exists());
bool sockExistsSync() {
return FileSystemEntity.typeSync(name) != FileSystemEntityType.notFound;
}
Future<bool> sockExists() async {
return await FileSystemEntity.type(name) != FileSystemEntityType.notFound;
}
Expect.isTrue(sockExistsSync());
Expect.isTrue(await sockExists());
file.deleteSync();
Expect.isFalse(file.existsSync());
Expect.isFalse(await file.exists());
Expect.isFalse(sockExistsSync());
Expect.isFalse(await sockExists());
await server.close();
server = await RawServerSocket.bind(address, 0, shared: false);
Expect.isTrue(file.existsSync());
Expect.isTrue(await file.exists());
Expect.isTrue(sockExistsSync());
Expect.isTrue(await sockExists());
await file.delete();
Expect.isFalse(file.existsSync());
Expect.isFalse(await file.exists());
Expect.isFalse(sockExistsSync());
Expect.isFalse(await sockExists());
await server.close();
}
@@ -1107,7 +1146,7 @@ Future testFileStat(String tempDirPath) async {
if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
return;
}
final name = '$tempDirPath/sock';
final name = p.join(tempDirPath, 'sock');
final address = InternetAddress(name, type: InternetAddressType.unix);
var server = await RawServerSocket.bind(address, 0, shared: false);
FileStat fileStat = FileStat.statSync(name);
@@ -1119,8 +1158,8 @@ Future testFileRename(String tempDirPath) async {
if (!Platform.isLinux && !Platform.isAndroid) {
return;
}
final name1 = '$tempDirPath/sock1';
final name2 = '$tempDirPath/sock2';
final name1 = p.join(tempDirPath, 'sock1');
final name2 = p.join(tempDirPath, 'sock2');
final address = InternetAddress(name1, type: InternetAddressType.unix);
var server = await RawServerSocket.bind(address, 0, shared: false);
final file1 = File(name1);
@@ -1137,8 +1176,8 @@ Future testFileCopy(String tempDirPath) async {
if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
return;
}
final name1 = '$tempDirPath/sock1';
final name2 = '$tempDirPath/sock2';
final name1 = p.join(tempDirPath, 'sock1');
final name2 = p.join(tempDirPath, 'sock2');
final address = InternetAddress(name1, type: InternetAddressType.unix);
final file1 = File(name1);
var server = await RawServerSocket.bind(address, 0, shared: false);
@@ -1226,7 +1265,10 @@ void main(List<String> args) async {
});
},
(e, st) {
if (Platform.isMacOS || Platform.isLinux || Platform.isAndroid) {
if (Platform.isWindows ||
Platform.isMacOS ||
Platform.isLinux ||
Platform.isAndroid) {
Expect.fail("Unexpected exception $e is thrown:\n$st");
} else {
Expect.isTrue(e is SocketException);