提交 0f79d723 编写于 作者: A Alexis Campailla

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.
上级 322d708f
......@@ -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) \
......@@ -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;
......@@ -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);
......@@ -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.
......@@ -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;
}
......
......@@ -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);
......@@ -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
......
......@@ -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);
......
......@@ -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;
......@@ -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;
}
......
......@@ -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';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册