Skip to content
This repository was archived by the owner on Feb 20, 2021. It is now read-only.

Commit 0f79d72

Browse files
committed
Workaround for getpeername() issue
getpeername() is returning invalid addresses on ipv6 sockets accepted with AcceptEx, filling only 16 bytes of the address structure. Providing a workaround by saving the remote address returned by GetAcceptExSockaddrs, which is valid.
1 parent 322d708 commit 0f79d72

File tree

5 files changed

+39
-4
lines changed

5 files changed

+39
-4
lines changed

src/Win32_Interop/win32_wsiocp.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929
#include "win32_wsiocp.h"
3030
#include "Win32_FDAPI.h"
3131
#include <errno.h>
32+
#include <assert.h>
3233

3334

3435
static void *iocpState;
3536
static HANDLE iocph;
3637
static fnGetSockState * aeGetSockState;
38+
static fnGetSockState * aeGetExistingSockState;
3739
static fnDelSockState * aeDelSockState;
3840

3941
#define SUCCEEDED_WITH_IOCP(result) \
@@ -130,6 +132,7 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) {
130132
SOCKADDR *premotesa;
131133
int locallen, remotelen;
132134
aacceptreq * areq;
135+
aeSockState *acceptsockstate;
133136

134137
if ((sockstate = aeGetSockState(iocpState, fd)) == NULL) {
135138
errno = WSAEINVAL;
@@ -169,6 +172,13 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) {
169172

170173
aeWinSocketAttach(acceptsock);
171174

175+
// Save remote address to support aeWinGetPeerName()
176+
if ((acceptsockstate = aeGetExistingSockState(iocpState, acceptsock)) == NULL) {
177+
errno = WSAEINVAL;
178+
return SOCKET_ERROR;
179+
}
180+
memcpy(&acceptsockstate->remoteAddress, premotesa, remotelen);
181+
172182
zfree(areq->buf);
173183
zfree(areq);
174184

@@ -180,6 +190,20 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) {
180190
return acceptsock;
181191
}
182192

193+
int aeWinGetPeerName(int fd, struct sockaddr *addr, socklen_t * addrlen) {
194+
aeSockState *sockState = aeGetExistingSockState(iocpState, fd);
195+
if (sockState == NULL) {
196+
errno = EBADF;
197+
return -1;
198+
} else {
199+
if (sockState->remoteAddress.ss_family) {
200+
memcpy(addr, &sockState->remoteAddress, *addrlen);
201+
return 0;
202+
} else {
203+
return getpeername(fd, addr, addrlen);
204+
}
205+
}
206+
}
183207

184208
/* after doing read caller needs to call done
185209
* so that we can continue to check for read events.
@@ -490,11 +514,15 @@ int aeWinCloseSocket(int fd) {
490514
return 0;
491515
}
492516

493-
void aeWinInit(void *state, HANDLE iocp, fnGetSockState *getSockState,
494-
fnDelSockState *delSockState) {
517+
void aeWinInit(void *state,
518+
HANDLE iocp,
519+
fnGetSockState *getSockState,
520+
fnGetSockState *getExistingSockState,
521+
fnDelSockState *delSockState) {
495522
iocpState = state;
496523
iocph = iocp;
497524
aeGetSockState = getSockState;
525+
aeGetExistingSockState = getExistingSockState;
498526
aeDelSockState = delSockState;
499527
}
500528

src/Win32_Interop/win32_wsiocp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ typedef struct aeSockState {
5656
int wreqs;
5757
OVERLAPPED ov_read;
5858
list wreqlist;
59+
SOCKADDR_STORAGE remoteAddress;
5960
} aeSockState;
6061

6162
typedef aeSockState * fnGetSockState(void *apistate, int fd);
@@ -68,7 +69,7 @@ typedef void fnDelSockState(void *apistate, aeSockState *sockState);
6869
#define CONNECT_PENDING 0x002000
6970
#define CLOSE_PENDING 0x004000
7071

71-
void aeWinInit(void *state, HANDLE iocp, fnGetSockState *getSockState, fnDelSockState *delSockState);
72+
void aeWinInit(void *state, HANDLE iocp, fnGetSockState *getSockState, fnGetSockState *getExistingSockState, fnDelSockState *delSockState);
7273
void aeWinCleanup();
7374

7475
#endif

src/Win32_Interop/win32fixes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ int aeWinSocketSend(int fd, char *buf, int len,
301301
void *eventLoop, void *client, void *data, void *proc);
302302
int aeWinListen(int rfd, int backlog);
303303
int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len);
304+
int aeWinGetPeerName(int fd, struct sockaddr *addr, socklen_t * addrlen);
304305
int aeWinSocketConnect(int fd, const SOCKADDR_STORAGE *ss);
305306
int aeWinSocketConnectBind(int fd, const SOCKADDR_STORAGE *ss, const char* source_addr);
306307

src/ae_wsiocp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ aeSockState *aeGetSockState(void *apistate, int fd) {
9090
sockState->wreqs = 0;
9191
sockState->reqs = NULL;
9292
memset(&sockState->wreqlist, 0, sizeof(sockState->wreqlist));
93+
memset(&sockState->remoteAddress, 0, sizeof(sockState->remoteAddress));
9394

9495
if (listAddNodeHead(socklist, sockState) != NULL) {
9596
return sockState;
@@ -202,7 +203,7 @@ static int aeApiCreate(aeEventLoop *eventLoop) {
202203
state->setsize = eventLoop->setsize;
203204
eventLoop->apidata = state;
204205
/* initialize the IOCP socket code with state reference */
205-
aeWinInit(state, state->iocp, aeGetSockState, aeDelSockState);
206+
aeWinInit(state, state->iocp, aeGetSockState, aeGetExistingSockState, aeDelSockState);
206207
return 0;
207208
}
208209

src/anet.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,11 @@ int anetPeerToString(int fd, char *ip, size_t ip_len, int *port) {
646646
struct sockaddr_storage sa;
647647
socklen_t salen = sizeof(sa);
648648

649+
#ifdef WIN32_IOCP
650+
if (aeWinGetPeerName(fd,(struct sockaddr*)&sa,&salen) == -1) {
651+
#else
649652
if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) {
653+
#endif
650654
if (port) *port = 0;
651655
ip[0] = '?';
652656
ip[1] = '\0';

0 commit comments

Comments
 (0)