Skip to content

Commit 4930359

Browse files
committed
Fix Socket remoteAddress obtaining on Win32 dart-lang#51778
1 parent 0c7c721 commit 4930359

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

runtime/bin/eventhandler_win.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,16 @@ bool ListenSocket::LoadAcceptEx() {
455455
return (status != SOCKET_ERROR);
456456
}
457457

458+
bool ListenSocket::LoadGetAcceptExSockaddrs() {
459+
// Load the LoadGetAcceptExSockaddrs function into memory using WSAIoctl.
460+
GUID guid_load_accept_ex_sockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
461+
DWORD bytes;
462+
int status = WSAIoctl(socket(), SIO_GET_EXTENSION_FUNCTION_POINTER,
463+
&guid_load_accept_ex_sockaddrs, sizeof(guid_load_accept_ex_sockaddrs), &GetAcceptExSockaddrs_,
464+
sizeof(GetAcceptExSockaddrs_), &bytes, NULL, NULL);
465+
return (status != SOCKET_ERROR);
466+
}
467+
458468
bool ListenSocket::IssueAccept() {
459469
MonitorLocker ml(&monitor_);
460470

@@ -498,8 +508,21 @@ void ListenSocket::AcceptComplete(OverlappedBuffer* buffer,
498508
int rc = setsockopt(buffer->client(), SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
499509
reinterpret_cast<char*>(&s), sizeof(s));
500510
if (rc == NO_ERROR) {
511+
LPSOCKADDR local_addr = 0;
512+
int local_addr_length = 0;
513+
LPSOCKADDR remote_addr = 0;
514+
int remote_addr_length = 0;
515+
static const int kAcceptExAddressAdditionalBytes = 16;
516+
static const int kAcceptExAddressStorageSize =
517+
sizeof(SOCKADDR_STORAGE) + kAcceptExAddressAdditionalBytes;
518+
GetAcceptExSockaddrs_(buffer->GetBufferStart(), 0, kAcceptExAddressStorageSize,
519+
kAcceptExAddressStorageSize, &local_addr, &local_addr_length,
520+
&remote_addr, &remote_addr_length);
521+
RawAddr* remote_addr_ = new RawAddr;
522+
memcpy(remote_addr_, remote_addr, remote_addr_length);
523+
501524
// Insert the accepted socket into the list.
502-
ClientSocket* client_socket = new ClientSocket(buffer->client());
525+
ClientSocket* client_socket = new ClientSocket(buffer->client(), remote_addr_);
503526
client_socket->mark_connected();
504527
client_socket->CreateCompletionPort(completion_port);
505528
if (accepted_head_ == NULL) {
@@ -559,6 +582,7 @@ void ListenSocket::DoClose() {
559582
// before EnsureInitialized was called, we have to reset the AcceptEx_
560583
// function pointer.
561584
AcceptEx_ = NULL;
585+
GetAcceptExSockaddrs_ = NULL;
562586
}
563587

564588
bool ListenSocket::CanAccept() {
@@ -603,6 +627,9 @@ void ListenSocket::EnsureInitialized(
603627
CreateCompletionPort(event_handler_->completion_port());
604628
LoadAcceptEx();
605629
}
630+
if (GetAcceptExSockaddrs_ == NULL) {
631+
LoadGetAcceptExSockaddrs();
632+
}
606633
}
607634

608635
bool ListenSocket::IsClosed() {

runtime/bin/eventhandler_win.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "bin/builtin.h"
1717
#include "bin/reference_counting.h"
1818
#include "bin/thread.h"
19+
#include "bin/socket_base.h"
1920

2021
namespace dart {
2122
namespace bin {
@@ -387,6 +388,7 @@ class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
387388
explicit ListenSocket(intptr_t s)
388389
: DescriptorInfoMultipleMixin(s, true),
389390
AcceptEx_(NULL),
391+
GetAcceptExSockaddrs_(NULL),
390392
pending_accept_count_(0),
391393
accepted_head_(NULL),
392394
accepted_tail_(NULL),
@@ -419,8 +421,12 @@ class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
419421
private:
420422
bool LoadAcceptEx();
421423

424+
bool LoadGetAcceptExSockaddrs();
425+
422426
LPFN_ACCEPTEX AcceptEx_;
423427

428+
LPFN_GETACCEPTEXSOCKADDRS GetAcceptExSockaddrs_;
429+
424430
// The number of asynchronous `IssueAccept` operations which haven't completed
425431
// yet.
426432
int pending_accept_count_;
@@ -440,12 +446,13 @@ class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
440446
// Information on connected sockets.
441447
class ClientSocket : public DescriptorInfoSingleMixin<SocketHandle> {
442448
public:
443-
explicit ClientSocket(intptr_t s)
449+
explicit ClientSocket(intptr_t s, RawAddr* premote_addr = NULL)
444450
: DescriptorInfoSingleMixin(s, true),
445451
DisconnectEx_(NULL),
446452
next_(NULL),
447453
connected_(false),
448-
closed_(false) {
454+
closed_(false),
455+
premote_addr_(premote_addr) {
449456
LoadDisconnectEx();
450457
type_ = kClientSocket;
451458
}
@@ -456,6 +463,7 @@ class ClientSocket : public DescriptorInfoSingleMixin<SocketHandle> {
456463
ASSERT(!HasPendingWrite());
457464
ASSERT(next_ == NULL);
458465
ASSERT(closed_ == true);
466+
delete premote_addr_;
459467
}
460468

461469
void Shutdown(int how);
@@ -480,6 +488,8 @@ class ClientSocket : public DescriptorInfoSingleMixin<SocketHandle> {
480488

481489
void mark_closed() { closed_ = true; }
482490

491+
RawAddr* const get_remote_addr() const { return premote_addr_;}
492+
483493
#if defined(DEBUG)
484494
static intptr_t disconnecting() { return disconnecting_; }
485495
#endif
@@ -491,6 +501,7 @@ class ClientSocket : public DescriptorInfoSingleMixin<SocketHandle> {
491501
ClientSocket* next_;
492502
bool connected_;
493503
bool closed_;
504+
RawAddr* premote_addr_;
494505

495506
#if defined(DEBUG)
496507
static intptr_t disconnecting_;

runtime/bin/socket_base_win.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,16 @@ intptr_t SocketBase::GetPort(intptr_t fd) {
181181
SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) {
182182
ASSERT(reinterpret_cast<Handle*>(fd)->is_socket());
183183
SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
184-
RawAddr raw;
185-
socklen_t size = sizeof(raw);
186-
if (getpeername(socket_handle->socket(), &raw.addr, &size)) {
187-
return NULL;
184+
RawAddr raw{};
185+
RawAddr* praw;
186+
if(socket_handle->is_client_socket() &&
187+
(praw = reinterpret_cast<ClientSocket*>(fd)->get_remote_addr())) {
188+
memcpy(&raw, praw, SocketAddress::GetAddrLength(*praw));
189+
} else {
190+
socklen_t size = sizeof(raw);
191+
if (getpeername(socket_handle->socket(), &raw.addr, &size)) {
192+
return NULL;
193+
}
188194
}
189195
*port = SocketAddress::GetAddrPort(raw);
190196
// Clear the port before calling WSAAddressToString as WSAAddressToString

0 commit comments

Comments
 (0)