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

Commit

Permalink
Workaround for getpeername() issue
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
orangemocha committed Feb 25, 2015
1 parent 322d708 commit 0f79d72
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 4 deletions.
32 changes: 30 additions & 2 deletions src/Win32_Interop/win32_wsiocp.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
#include "win32_wsiocp.h"
#include "Win32_FDAPI.h"
#include <errno.h>
#include <assert.h>


static void *iocpState;
static HANDLE iocph;
static fnGetSockState * aeGetSockState;
static fnGetSockState * aeGetExistingSockState;
static fnDelSockState * aeDelSockState;

#define SUCCEEDED_WITH_IOCP(result) \
Expand Down Expand Up @@ -130,6 +132,7 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) {
SOCKADDR *premotesa;
int locallen, remotelen;
aacceptreq * areq;
aeSockState *acceptsockstate;

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

aeWinSocketAttach(acceptsock);

// Save remote address to support aeWinGetPeerName()
if ((acceptsockstate = aeGetExistingSockState(iocpState, acceptsock)) == NULL) {
errno = WSAEINVAL;
return SOCKET_ERROR;
}
memcpy(&acceptsockstate->remoteAddress, premotesa, remotelen);

zfree(areq->buf);
zfree(areq);

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

int aeWinGetPeerName(int fd, struct sockaddr *addr, socklen_t * addrlen) {
aeSockState *sockState = aeGetExistingSockState(iocpState, fd);
if (sockState == NULL) {
errno = EBADF;
return -1;
} else {
if (sockState->remoteAddress.ss_family) {
memcpy(addr, &sockState->remoteAddress, *addrlen);
return 0;
} else {
return getpeername(fd, addr, addrlen);
}
}
}

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

void aeWinInit(void *state, HANDLE iocp, fnGetSockState *getSockState,
fnDelSockState *delSockState) {
void aeWinInit(void *state,
HANDLE iocp,
fnGetSockState *getSockState,
fnGetSockState *getExistingSockState,
fnDelSockState *delSockState) {
iocpState = state;
iocph = iocp;
aeGetSockState = getSockState;
aeGetExistingSockState = getExistingSockState;
aeDelSockState = delSockState;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Win32_Interop/win32_wsiocp.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ typedef struct aeSockState {
int wreqs;
OVERLAPPED ov_read;
list wreqlist;
SOCKADDR_STORAGE remoteAddress;
} aeSockState;

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

void aeWinInit(void *state, HANDLE iocp, fnGetSockState *getSockState, fnDelSockState *delSockState);
void aeWinInit(void *state, HANDLE iocp, fnGetSockState *getSockState, fnGetSockState *getExistingSockState, fnDelSockState *delSockState);
void aeWinCleanup();

#endif
Expand Down
1 change: 1 addition & 0 deletions src/Win32_Interop/win32fixes.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ int aeWinSocketSend(int fd, char *buf, int len,
void *eventLoop, void *client, void *data, void *proc);
int aeWinListen(int rfd, int backlog);
int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len);
int aeWinGetPeerName(int fd, struct sockaddr *addr, socklen_t * addrlen);
int aeWinSocketConnect(int fd, const SOCKADDR_STORAGE *ss);
int aeWinSocketConnectBind(int fd, const SOCKADDR_STORAGE *ss, const char* source_addr);

Expand Down
3 changes: 2 additions & 1 deletion src/ae_wsiocp.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ aeSockState *aeGetSockState(void *apistate, int fd) {
sockState->wreqs = 0;
sockState->reqs = NULL;
memset(&sockState->wreqlist, 0, sizeof(sockState->wreqlist));
memset(&sockState->remoteAddress, 0, sizeof(sockState->remoteAddress));

if (listAddNodeHead(socklist, sockState) != NULL) {
return sockState;
Expand Down Expand Up @@ -202,7 +203,7 @@ static int aeApiCreate(aeEventLoop *eventLoop) {
state->setsize = eventLoop->setsize;
eventLoop->apidata = state;
/* initialize the IOCP socket code with state reference */
aeWinInit(state, state->iocp, aeGetSockState, aeDelSockState);
aeWinInit(state, state->iocp, aeGetSockState, aeGetExistingSockState, aeDelSockState);
return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/anet.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,11 @@ int anetPeerToString(int fd, char *ip, size_t ip_len, int *port) {
struct sockaddr_storage sa;
socklen_t salen = sizeof(sa);

#ifdef WIN32_IOCP
if (aeWinGetPeerName(fd,(struct sockaddr*)&sa,&salen) == -1) {
#else
if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) {
#endif
if (port) *port = 0;
ip[0] = '?';
ip[1] = '\0';
Expand Down

0 comments on commit 0f79d72

Please sign in to comment.