mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-30 05:56:12 +00:00
merge code from xml-rpc trunk - fix xml-rpc not terminating on windows on fs unload - only effect windows build
This commit is contained in:
parent
b55db357d9
commit
6f103acd79
@ -9,8 +9,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <winsock.h>
|
#include <winsock2.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "xmlrpc_config.h"
|
#include "xmlrpc_config.h"
|
||||||
#include "xmlrpc-c/util_int.h"
|
#include "xmlrpc-c/util_int.h"
|
||||||
@ -249,6 +248,7 @@ struct socketWin {
|
|||||||
SOCKET winsock;
|
SOCKET winsock;
|
||||||
bool userSuppliedWinsock;
|
bool userSuppliedWinsock;
|
||||||
/* 'socket' was supplied by the user; it belongs to him */
|
/* 'socket' was supplied by the user; it belongs to him */
|
||||||
|
HANDLE interruptEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -322,6 +322,8 @@ channelDestroy(TChannel * const channelP) {
|
|||||||
if (!socketWinP->userSuppliedWinsock)
|
if (!socketWinP->userSuppliedWinsock)
|
||||||
closesocket(socketWinP->winsock);
|
closesocket(socketWinP->winsock);
|
||||||
|
|
||||||
|
CloseHandle(socketWinP->interruptEvent);
|
||||||
|
|
||||||
free(socketWinP);
|
free(socketWinP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +432,7 @@ channelWait(TChannel * const channelP,
|
|||||||
timedOut = TRUE;
|
timedOut = TRUE;
|
||||||
break;
|
break;
|
||||||
case -1: /* socket error */
|
case -1: /* socket error */
|
||||||
if (errno != EINTR)
|
if (WSAGetLastError() != WSAEINTR)
|
||||||
failed = TRUE;
|
failed = TRUE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -460,7 +462,9 @@ channelInterrupt(TChannel * const channelP) {
|
|||||||
now or in the future.
|
now or in the future.
|
||||||
|
|
||||||
Actually, this is just a no-op because we don't yet know how to
|
Actually, this is just a no-op because we don't yet know how to
|
||||||
accomplish that.
|
accomplish that. (But we could probably do it the same way
|
||||||
|
chanSwitchInterrupt() works -- no one has needed it enough yet to do that
|
||||||
|
work).
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -484,7 +488,7 @@ ChannelWinGetPeerName(TChannel * const channelP,
|
|||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
int const lastError = WSAGetLastError();
|
int const lastError = WSAGetLastError();
|
||||||
xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)",
|
xmlrpc_asprintf(errorP, "getpeername() failed. WSA error = %d (%s)",
|
||||||
lastError, getWSAError(lastError));
|
lastError, getWSAError(lastError));
|
||||||
} else {
|
} else {
|
||||||
if (addrlen != sizeof(sockAddr))
|
if (addrlen != sizeof(sockAddr))
|
||||||
@ -581,6 +585,7 @@ makeChannelFromWinsock(SOCKET const winsock,
|
|||||||
|
|
||||||
socketWinP->winsock = winsock;
|
socketWinP->winsock = winsock;
|
||||||
socketWinP->userSuppliedWinsock = TRUE;
|
socketWinP->userSuppliedWinsock = TRUE;
|
||||||
|
socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
ChannelCreate(&channelVtbl, socketWinP, &channelP);
|
ChannelCreate(&channelVtbl, socketWinP, &channelP);
|
||||||
|
|
||||||
@ -591,10 +596,12 @@ makeChannelFromWinsock(SOCKET const winsock,
|
|||||||
*channelPP = channelP;
|
*channelPP = channelP;
|
||||||
*errorP = NULL;
|
*errorP = NULL;
|
||||||
}
|
}
|
||||||
if (*errorP)
|
if (*errorP) {
|
||||||
|
CloseHandle(socketWinP->interruptEvent);
|
||||||
free(socketWinP);
|
free(socketWinP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -632,7 +639,7 @@ ChannelWinCreateWinsock(SOCKET const fd,
|
|||||||
socklen_t peerAddrLen;
|
socklen_t peerAddrLen;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
peerAddrLen = sizeof(peerAddrLen);
|
peerAddrLen = sizeof(peerAddr);
|
||||||
|
|
||||||
rc = getpeername(fd, &peerAddr, &peerAddrLen);
|
rc = getpeername(fd, &peerAddr, &peerAddrLen);
|
||||||
|
|
||||||
@ -676,6 +683,8 @@ chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
|
|||||||
if (!socketWinP->userSuppliedWinsock)
|
if (!socketWinP->userSuppliedWinsock)
|
||||||
closesocket(socketWinP->winsock);
|
closesocket(socketWinP->winsock);
|
||||||
|
|
||||||
|
CloseHandle(socketWinP->interruptEvent);
|
||||||
|
|
||||||
free(socketWinP);
|
free(socketWinP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -711,6 +720,49 @@ chanSwitchListen(TChanSwitch * const chanSwitchP,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
createChannelForAccept(int const acceptedWinsock,
|
||||||
|
struct sockaddr const peerAddr,
|
||||||
|
TChannel ** const channelPP,
|
||||||
|
void ** const channelInfoPP,
|
||||||
|
const char ** const errorP) {
|
||||||
|
|
||||||
|
struct abyss_win_chaninfo * channelInfoP;
|
||||||
|
makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP);
|
||||||
|
if (!*errorP) {
|
||||||
|
struct socketWin * acceptedSocketP;
|
||||||
|
|
||||||
|
MALLOCVAR(acceptedSocketP);
|
||||||
|
|
||||||
|
if (!acceptedSocketP)
|
||||||
|
xmlrpc_asprintf(errorP, "Unable to allocate memory");
|
||||||
|
else {
|
||||||
|
TChannel * channelP;
|
||||||
|
|
||||||
|
acceptedSocketP->winsock = acceptedWinsock;
|
||||||
|
acceptedSocketP->userSuppliedWinsock = FALSE;
|
||||||
|
acceptedSocketP->interruptEvent =
|
||||||
|
CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
|
ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
|
||||||
|
if (!channelP)
|
||||||
|
xmlrpc_asprintf(errorP,
|
||||||
|
"Failed to create TChannel object.");
|
||||||
|
else {
|
||||||
|
*errorP = NULL;
|
||||||
|
*channelPP = channelP;
|
||||||
|
*channelInfoPP = channelInfoP;
|
||||||
|
}
|
||||||
|
if (*errorP) {
|
||||||
|
CloseHandle(acceptedSocketP->interruptEvent);
|
||||||
|
free(acceptedSocketP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static SwitchAcceptImpl chanSwitchAccept;
|
static SwitchAcceptImpl chanSwitchAccept;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -728,7 +780,7 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP,
|
|||||||
*channelPP == NULL.
|
*channelPP == NULL.
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
struct socketWin * const listenSocketP = chanSwitchP->implP;
|
struct socketWin * const listenSocketP = chanSwitchP->implP;
|
||||||
|
HANDLE acceptEvent = WSACreateEvent();
|
||||||
bool interrupted;
|
bool interrupted;
|
||||||
TChannel * channelP;
|
TChannel * channelP;
|
||||||
|
|
||||||
@ -736,46 +788,44 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP,
|
|||||||
channelP = NULL; /* No connection yet */
|
channelP = NULL; /* No connection yet */
|
||||||
*errorP = NULL; /* No error yet */
|
*errorP = NULL; /* No error yet */
|
||||||
|
|
||||||
|
WSAEventSelect(listenSocketP->winsock, acceptEvent,
|
||||||
|
FD_ACCEPT | FD_CLOSE | FD_READ);
|
||||||
|
|
||||||
while (!channelP && !*errorP && !interrupted) {
|
while (!channelP && !*errorP && !interrupted) {
|
||||||
|
HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent};
|
||||||
|
int rc;
|
||||||
struct sockaddr peerAddr;
|
struct sockaddr peerAddr;
|
||||||
socklen_t size = sizeof(peerAddr);
|
socklen_t size = sizeof(peerAddr);
|
||||||
int rc;
|
|
||||||
|
rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE);
|
||||||
|
if (WAIT_OBJECT_0 + 1 == rc) {
|
||||||
|
interrupted = TRUE;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
rc = accept(listenSocketP->winsock, &peerAddr, &size);
|
rc = accept(listenSocketP->winsock, &peerAddr, &size);
|
||||||
|
|
||||||
if (rc >= 0) {
|
if (rc >= 0) {
|
||||||
int const acceptedWinsock = rc;
|
int const acceptedWinsock = rc;
|
||||||
struct socketWin * acceptedSocketP;
|
|
||||||
|
|
||||||
MALLOCVAR(acceptedSocketP);
|
createChannelForAccept(acceptedWinsock, peerAddr,
|
||||||
|
&channelP, channelInfoPP, errorP);
|
||||||
|
|
||||||
if (!acceptedSocketP)
|
|
||||||
xmlrpc_asprintf(errorP, "Unable to allocate memory");
|
|
||||||
else {
|
|
||||||
acceptedSocketP->winsock = acceptedWinsock;
|
|
||||||
acceptedSocketP->userSuppliedWinsock = FALSE;
|
|
||||||
|
|
||||||
*channelInfoPP = NULL;
|
|
||||||
|
|
||||||
ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
|
|
||||||
if (!channelP)
|
|
||||||
xmlrpc_asprintf(errorP,
|
|
||||||
"Failed to create TChannel object.");
|
|
||||||
else
|
|
||||||
*errorP = NULL;
|
|
||||||
|
|
||||||
if (*errorP)
|
|
||||||
free(acceptedSocketP);
|
|
||||||
}
|
|
||||||
if (*errorP)
|
if (*errorP)
|
||||||
closesocket(acceptedWinsock);
|
closesocket(acceptedWinsock);
|
||||||
} else if (errno == EINTR)
|
} else {
|
||||||
|
int const lastError = WSAGetLastError();
|
||||||
|
|
||||||
|
if (lastError == WSAEINTR)
|
||||||
interrupted = TRUE;
|
interrupted = TRUE;
|
||||||
else
|
else
|
||||||
xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)",
|
xmlrpc_asprintf(errorP,
|
||||||
errno, strerror(errno));
|
"accept() failed, WSA error = %d (%s)",
|
||||||
|
lastError, getWSAError(lastError));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*channelPP = channelP;
|
*channelPP = channelP;
|
||||||
|
CloseHandle(acceptEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -787,15 +837,10 @@ chanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
|
|||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
Interrupt any waiting that a thread might be doing in chanSwitchAccept()
|
Interrupt any waiting that a thread might be doing in chanSwitchAccept()
|
||||||
now or in the future.
|
now or in the future.
|
||||||
|
|
||||||
Actually, this is just a no-op because we don't yet know how to
|
|
||||||
accomplish that.
|
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
struct socketWin * const socketWinP = chanSwitchP->implP;
|
struct socketWin * const listenSocketP = chanSwitchP->implP;
|
||||||
|
|
||||||
if (!socketWinP->userSuppliedWinsock)
|
|
||||||
closesocket(socketWinP->winsock);
|
|
||||||
|
|
||||||
|
SetEvent(listenSocketP->interruptEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -889,6 +934,7 @@ ChanSwitchWinCreate(uint16_t const portNumber,
|
|||||||
} else {
|
} else {
|
||||||
socketWinP->winsock = winsock;
|
socketWinP->winsock = winsock;
|
||||||
socketWinP->userSuppliedWinsock = FALSE;
|
socketWinP->userSuppliedWinsock = FALSE;
|
||||||
|
socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
setSocketOptions(socketWinP->winsock, errorP);
|
setSocketOptions(socketWinP->winsock, errorP);
|
||||||
if (!*errorP) {
|
if (!*errorP) {
|
||||||
@ -899,9 +945,11 @@ ChanSwitchWinCreate(uint16_t const portNumber,
|
|||||||
chanSwitchPP);
|
chanSwitchPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*errorP)
|
if (*errorP) {
|
||||||
|
CloseHandle(socketWinP->interruptEvent);
|
||||||
closesocket(winsock);
|
closesocket(winsock);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (*errorP)
|
if (*errorP)
|
||||||
free(socketWinP);
|
free(socketWinP);
|
||||||
}
|
}
|
||||||
@ -929,6 +977,7 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock,
|
|||||||
|
|
||||||
socketWinP->winsock = winsock;
|
socketWinP->winsock = winsock;
|
||||||
socketWinP->userSuppliedWinsock = TRUE;
|
socketWinP->userSuppliedWinsock = TRUE;
|
||||||
|
socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
ChanSwitchCreate(&chanSwitchVtbl, socketWinP, &chanSwitchP);
|
ChanSwitchCreate(&chanSwitchVtbl, socketWinP, &chanSwitchP);
|
||||||
|
|
||||||
@ -939,8 +988,10 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock,
|
|||||||
*chanSwitchPP = chanSwitchP;
|
*chanSwitchPP = chanSwitchP;
|
||||||
*errorP = NULL;
|
*errorP = NULL;
|
||||||
}
|
}
|
||||||
if (*errorP)
|
if (*errorP) {
|
||||||
|
CloseHandle(socketWinP->interruptEvent);
|
||||||
free(socketWinP);
|
free(socketWinP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user