mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1432 lines
36 KiB
1432 lines
36 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
common.c
|
|
|
|
Abstract:
|
|
|
|
|
|
Revision History:
|
|
Mazhar Mohammed Consolidated winsock transports
|
|
Mazhar Mohammed added thread migration support
|
|
tony chan (tonychan) move common routines to common.c
|
|
tony chan added NetBios support
|
|
|
|
Comments:
|
|
|
|
This file contains common code for RPC transport dlls using Winsock.
|
|
|
|
--*/
|
|
|
|
|
|
#include "common.h"
|
|
|
|
int initialized = 0;
|
|
PRIMARYADDR PrimaryAddress ;
|
|
|
|
// WARNING: The order of these protocols must be consistent with the constants
|
|
TRANSTAB TransportTab[] = {
|
|
|
|
{ RPC_CONST_STRING("ncacn_ip_tcp"),
|
|
TCP_TransportLoad,
|
|
NCACN_IP_TCP,
|
|
COMMON_ServerReceive,
|
|
FALSE
|
|
},
|
|
|
|
{ RPC_CONST_STRING("ncacn_spx"),
|
|
SPX_TransportLoad,
|
|
NCACN_SPX,
|
|
COMMON_ServerReceive,
|
|
FALSE
|
|
},
|
|
|
|
#ifdef NTENV
|
|
{ RPC_CONST_STRING("ncacn_at_dsp"),
|
|
ADSP_TransportLoad,
|
|
NCACN_ADSP,
|
|
ADSP_ServerReceive,
|
|
FALSE
|
|
},
|
|
|
|
{ RPC_CONST_STRING("ncacn_nb_nb"),
|
|
NB_TransportLoad,
|
|
NCACN_NB_NB,
|
|
NB_ServerReceive,
|
|
FALSE
|
|
},
|
|
|
|
{ RPC_CONST_STRING("ncacn_nb_tcp"),
|
|
NB_TransportLoad,
|
|
NCACN_NB_TCP,
|
|
NB_ServerReceive,
|
|
FALSE
|
|
},
|
|
|
|
{ RPC_CONST_STRING("ncacn_nb_ipx"),
|
|
NB_TransportLoad,
|
|
NCACN_NB_IPX,
|
|
NB_ServerReceive,
|
|
FALSE
|
|
},
|
|
#endif // NTENV
|
|
|
|
#if defined (WIN96) || defined (NTENV)
|
|
{ RPC_CONST_STRING("ncadg_ip_udp"),
|
|
UDP_TransportLoad,
|
|
NCADG_IP_UDP,
|
|
DG_ServerReceive,
|
|
TRUE
|
|
},
|
|
|
|
{ RPC_CONST_STRING("ncadg_ipx"),
|
|
IPX_TransportLoad,
|
|
NCADG_IPX,
|
|
DG_ServerReceive,
|
|
TRUE
|
|
},
|
|
#endif // defined (WIN96) || defined (NTENV)
|
|
|
|
{ NULL,
|
|
NULL,
|
|
0,
|
|
NULL}
|
|
} ;
|
|
|
|
|
|
RPC_STATUS
|
|
GrowMap(
|
|
BOOL bIsListenMap
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Grows the Listen on Data Map
|
|
this routine must be called from within a critical section
|
|
|
|
Arguments:
|
|
bIsListenMap:
|
|
TRUE: Grow the Listen Map
|
|
FALSE: Grow the Data Map
|
|
|
|
--*/
|
|
{
|
|
PSOCKMAP *pMap ;
|
|
PSOCKMAP *pOldMap ;
|
|
MAPINFO *pMapInfo ;
|
|
PSOCKMAP TempMapPtr;
|
|
unsigned i, j ;
|
|
|
|
|
|
if(bIsListenMap)
|
|
{
|
|
pMap = &(PrimaryAddress.ListenSockMap) ;
|
|
pOldMap = &(PrimaryAddress.PreviousListenMap) ;
|
|
pMapInfo = &(PrimaryAddress.ListenMapInfo) ;
|
|
}
|
|
else
|
|
{
|
|
pMap = &(PrimaryAddress.DataSockMap) ;
|
|
pOldMap = &(PrimaryAddress.PreviousDataMap) ;
|
|
pMapInfo = &(PrimaryAddress.DataMapInfo) ;
|
|
}
|
|
|
|
i = 0;
|
|
for(;;)
|
|
{
|
|
if ((*pMap)[i].Sock == 0)
|
|
break; // found room
|
|
|
|
if (i == pMapInfo->MaxEntries - 1)
|
|
{
|
|
// No room in current Map, grow it
|
|
TempMapPtr = *pMap;
|
|
*pMap = I_RpcAllocate(2 * pMapInfo->MaxEntries * sizeof(SOCKMAP));
|
|
|
|
if (*pMap == 0)
|
|
{
|
|
*pMap = TempMapPtr;
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
//
|
|
// Copy old table to first half of new...
|
|
//
|
|
memcpy (*pMap, TempMapPtr,
|
|
pMapInfo->MaxEntries * sizeof(SOCKMAP));
|
|
|
|
//
|
|
// Initialize all new entries...
|
|
//
|
|
for (j=pMapInfo->MaxEntries; j < (2*pMapInfo->MaxEntries); j++ )
|
|
{
|
|
(*pMap)[j].Sock = 0;
|
|
}
|
|
|
|
pMapInfo->MaxEntries *= 2;
|
|
|
|
if (*pOldMap == 0)
|
|
{
|
|
*pOldMap = TempMapPtr ;
|
|
}
|
|
else
|
|
{
|
|
// Free old table
|
|
I_RpcFree ( TempMapPtr );
|
|
}
|
|
|
|
break; // made room
|
|
}
|
|
|
|
i++; // try next entry
|
|
}
|
|
|
|
return (RPC_S_OK) ;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
GrowMask(
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Grows the Mask and MasterMask
|
|
this routine must be called from within a critical section
|
|
--*/
|
|
{
|
|
fd_big_set *TempMaskPtr;
|
|
|
|
if (PrimaryAddress.MasterMask->fd_count == PrimaryAddress.MaskSize)
|
|
{
|
|
TempMaskPtr = PrimaryAddress.MasterMask;
|
|
PrimaryAddress.MasterMask = I_RpcAllocate(sizeof(fd_big_set) +
|
|
2 * sizeof(SOCKET) * PrimaryAddress.MaskSize);
|
|
if (PrimaryAddress.MasterMask == 0)
|
|
{
|
|
PrimaryAddress.MasterMask = TempMaskPtr;
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
// copy old mask entries
|
|
memcpy(PrimaryAddress.MasterMask, TempMaskPtr,
|
|
sizeof(fd_big_set) + sizeof(SOCKET) * PrimaryAddress.MaskSize);
|
|
|
|
// free old MasterMask
|
|
I_RpcFree(TempMaskPtr);
|
|
|
|
TempMaskPtr = PrimaryAddress.Mask;
|
|
PrimaryAddress.Mask = I_RpcAllocate(sizeof(fd_big_set) +
|
|
2 * sizeof(SOCKET) * PrimaryAddress.MaskSize);
|
|
if (PrimaryAddress.Mask == 0)
|
|
{
|
|
PrimaryAddress.Mask = TempMaskPtr;
|
|
// We didn't update Address->MaskSize, so the size
|
|
// difference between MasterMask and Mask will be okay.
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
// copy old mask entries
|
|
memcpy(PrimaryAddress.Mask, TempMaskPtr,
|
|
sizeof(fd_big_set) + sizeof(SOCKET) * PrimaryAddress.MaskSize);
|
|
|
|
if (PrimaryAddress.PreviousMask == 0)
|
|
{
|
|
PrimaryAddress.PreviousMask = TempMaskPtr ;
|
|
}
|
|
else
|
|
{
|
|
// Free old Mask
|
|
I_RpcFree(TempMaskPtr);
|
|
}
|
|
|
|
PrimaryAddress.MaskSize *= 2;
|
|
}
|
|
return (RPC_S_OK) ;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
AddSyncSocket(
|
|
SOCKET socket
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Adds a SyncSocket to the Mask.
|
|
this routine must be called from within a critical section.
|
|
There is only one sync socket.
|
|
|
|
Arguments:
|
|
socket: The sync socket to be added
|
|
--*/
|
|
{
|
|
RPC_STATUS status ;
|
|
int i ;
|
|
|
|
//
|
|
// Grow mask if neccassary.
|
|
//
|
|
if((status = GrowMask()) != RPC_S_OK)
|
|
return status ;
|
|
|
|
PrimaryAddress.SyncSock = socket ;
|
|
FD_BIG_SET(socket, PrimaryAddress) ;
|
|
|
|
return (RPC_S_OK) ;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
InsertDataSocket(
|
|
PADDRESS Address,
|
|
BOOL bIsListenMap,
|
|
SOCKET Socket,
|
|
PSCONNECTION pConn,
|
|
int ProtocolId
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Adds a Data or Listen socket to the Mask and Map
|
|
this routine must be called from within a critical section.
|
|
This function is also called from the macro AddListenSocket
|
|
|
|
Arguments:
|
|
Address: The address corresponding the socket
|
|
bIsListenMap:
|
|
TRUE: the socket is a listen socket
|
|
FALSE: the socket is a data socket
|
|
Socket: Socket to be added
|
|
pConn: the sconnection corresponding to the socket
|
|
|
|
--*/
|
|
{
|
|
PSOCKMAP *pMap ;
|
|
MAPINFO *pMapInfo ;
|
|
unsigned i;
|
|
RPC_STATUS status ;
|
|
|
|
|
|
#if DBG
|
|
if (Socket == INVALID_SOCKET)
|
|
{
|
|
PrintToDebugger("RPCLTSCM: Bad socket passed to InsertDataSocket\n") ;
|
|
|
|
ASSERT(0) ;
|
|
return (RPC_S_OUT_OF_MEMORY) ;
|
|
}
|
|
#endif
|
|
|
|
if (FD_ISSET(Socket, PrimaryAddress.Mask))
|
|
{
|
|
return RPC_S_OK ;
|
|
}
|
|
|
|
//
|
|
// Grow mask if neccassary
|
|
//
|
|
if((status = GrowMask()) != RPC_S_OK)
|
|
return status ;
|
|
|
|
//
|
|
// Grow map if neccassary
|
|
//
|
|
if((status = GrowMap(bIsListenMap)) != RPC_S_OK)
|
|
return status ;
|
|
|
|
if(bIsListenMap)
|
|
{
|
|
pMap = &(PrimaryAddress.ListenSockMap) ;
|
|
pMapInfo = &(PrimaryAddress.ListenMapInfo) ;
|
|
}
|
|
else
|
|
{
|
|
pMap = &(PrimaryAddress.DataSockMap) ;
|
|
pMapInfo = &(PrimaryAddress.DataMapInfo) ;
|
|
}
|
|
|
|
for (i=0; i < pMapInfo->MaxEntries; i++)
|
|
{
|
|
if ((*pMap)[i].Sock == 0)
|
|
{
|
|
(*pMap)[i].Sock = Socket;
|
|
(*pMap)[i].Conn = pConn ;
|
|
(*pMap)[i].ProtocolId = ProtocolId ;
|
|
(*pMap)[i].pAddress = (void *) Address ;
|
|
|
|
if (i > pMapInfo->LastEntry)
|
|
{
|
|
pMapInfo->LastEntry = i;
|
|
}
|
|
|
|
FD_BIG_SET(Socket, PrimaryAddress) ;
|
|
return RPC_S_OK;
|
|
}
|
|
}
|
|
|
|
return RPC_S_OUT_OF_MEMORY;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
DeleteDataSocket(
|
|
SOCKET Socket)
|
|
/*++
|
|
Routine Description:
|
|
Deletes a Data socket from the Mask and Map
|
|
this routine must be called from within a critical section.
|
|
|
|
Arguments:
|
|
Socket: The socket to be deleted
|
|
--*/
|
|
{
|
|
unsigned i ;
|
|
|
|
for (i=0; i <= PrimaryAddress.DataMapInfo.LastEntry; i++)
|
|
{
|
|
if (Socket == PrimaryAddress.DataSockMap[i].Sock)
|
|
{
|
|
memset((char *) &(PrimaryAddress.DataSockMap[i]),
|
|
0, sizeof(SOCKMAP)) ;
|
|
|
|
if (i == PrimaryAddress.DataMapInfo.LastEntry)
|
|
PrimaryAddress.DataMapInfo.LastEntry--;
|
|
|
|
FD_CLR(Socket, PrimaryAddress.MasterMask);
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
}
|
|
|
|
return (RPC_S_OUT_OF_MEMORY) ;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
DeleteListenSocket(
|
|
SOCKET Socket)
|
|
/*++
|
|
Routine Description:
|
|
Deletes a Listen socket from the Mask and Map
|
|
this routine must be called from within a critical section.
|
|
|
|
Arguments:
|
|
Socket: The socket to be deleted
|
|
--*/
|
|
{
|
|
unsigned i ;
|
|
|
|
for (i=0; i <= PrimaryAddress.ListenMapInfo.LastEntry; i++)
|
|
{
|
|
if (Socket == PrimaryAddress.ListenSockMap[i].Sock)
|
|
{
|
|
memset((char *) &(PrimaryAddress.ListenSockMap[i]),
|
|
0, sizeof(SOCKMAP)) ;
|
|
|
|
if (i == PrimaryAddress.ListenMapInfo.LastEntry)
|
|
PrimaryAddress.ListenMapInfo.LastEntry--;
|
|
|
|
FD_CLR(Socket, PrimaryAddress.MasterMask);
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
}
|
|
|
|
return (RPC_S_OUT_OF_MEMORY) ;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
AcceptNewConnection (
|
|
int Index
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Accepts a new connection.
|
|
This rountine must be called from within a critical section
|
|
--*/
|
|
{
|
|
PSCONNECTION NewSConnection;
|
|
int i, j;
|
|
SOCKET isock;
|
|
int SetNaglingOff = TRUE;
|
|
unsigned int ReceiveDirectFlag ;
|
|
int SocketOptionsValue ;
|
|
RPC_STATUS status ;
|
|
static int KeepAliveOn = 1;
|
|
RPC_STATUS Status;
|
|
int SockOpt ;
|
|
PADDRESS MyAddress = (PADDRESS) PrimaryAddress.ListenSockMap[Index].pAddress;
|
|
|
|
//
|
|
//
|
|
// Accept the connection
|
|
//
|
|
isock = accept ( PrimaryAddress.ListenSockMap[Index].Sock, NULL, NULL );
|
|
if (isock == INVALID_SOCKET)
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY) ;
|
|
}
|
|
|
|
if(PrimaryAddress.ListenSockMap[Index].ProtocolId == NCACN_IP_TCP)
|
|
{
|
|
setsockopt( isock, IPPROTO_TCP, TCP_NODELAY,
|
|
(char FAR *)&SetNaglingOff, sizeof (int) );
|
|
|
|
setsockopt( isock, IPPROTO_TCP, SO_KEEPALIVE,
|
|
(char *)&KeepAliveOn, sizeof(KeepAliveOn) );
|
|
}
|
|
|
|
//
|
|
// Allocate new connection structure
|
|
//
|
|
NewSConnection = I_RpcTransServerNewConnection ( MyAddress, 0,
|
|
&ReceiveDirectFlag);
|
|
|
|
if ( NewSConnection == 0 )
|
|
{
|
|
// We're out of memory, abort the connection...
|
|
j = TRUE;
|
|
i = setsockopt( isock, SOL_SOCKET, SO_DONTLINGER, (const char *) &j,
|
|
sizeof(j));
|
|
|
|
ASSERT(i == 0);
|
|
|
|
i = closesocket( isock);
|
|
|
|
ASSERT(i == 0);
|
|
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
/* For NetBIOS only */
|
|
/* set old_client to -1 for later verification */
|
|
NewSConnection->old_client = -1;
|
|
|
|
// Initialize new connection structure...
|
|
//
|
|
// ...point to owning address structure...
|
|
//
|
|
NewSConnection->Address = MyAddress;
|
|
|
|
//
|
|
// ...flag it !Closed...
|
|
//
|
|
NewSConnection->ConnSockClosed = -1;
|
|
//
|
|
// ...store the socket number...
|
|
//
|
|
NewSConnection->ConnSock = isock;
|
|
//
|
|
// ...save the receive direct flag
|
|
//
|
|
NewSConnection->ReceiveDirectFlag = ReceiveDirectFlag;
|
|
|
|
NewSConnection->ProtocolId = PrimaryAddress.ListenSockMap[Index].ProtocolId ;
|
|
|
|
//
|
|
// ...increment the number of connections...
|
|
//
|
|
PrimaryAddress.NumConnections++;
|
|
|
|
NewSConnection->CoalescedBuffer = NULL;
|
|
NewSConnection->CoalescedBufferLength = 0;
|
|
//
|
|
// ...last but not least, make an entry in
|
|
// the SOCKMAP table. But only if it is not marked ReceiveDirect.
|
|
//
|
|
if (ReceiveDirectFlag)
|
|
{
|
|
SockOpt = RECV_TIMEOUT ;
|
|
if (setsockopt( isock, SOL_SOCKET, SO_RCVTIMEO,
|
|
(char *) &SockOpt, sizeof(SockOpt) ) != 0)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: setsockopt failed: %d\n",
|
|
WSAGetLastError()) ;
|
|
|
|
ASSERT(0) ;
|
|
#endif
|
|
}
|
|
I_RpcTransServerReceiveDirectReady(NewSConnection);
|
|
|
|
return (RPC_S_OK);
|
|
}
|
|
|
|
if (NewSConnection->ProtocolId == NCACN_IP_TCP ||
|
|
NewSConnection->ProtocolId == NCACN_SPX)
|
|
{
|
|
SocketOptionsValue = RECV_ANY_TIMEOUT_TCPSPX ;
|
|
}
|
|
else
|
|
{
|
|
SocketOptionsValue = RECV_ANY_TIMEOUT ;
|
|
}
|
|
|
|
if (setsockopt( isock, SOL_SOCKET, SO_RCVTIMEO,
|
|
(char *) &SocketOptionsValue, sizeof(SocketOptionsValue) ) != 0)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: setsockopt failed: %d\n",
|
|
WSAGetLastError()) ;
|
|
|
|
ASSERT(0) ;
|
|
#endif
|
|
}
|
|
|
|
Status = InsertDataSocket(MyAddress, FALSE, isock,
|
|
NewSConnection, PrimaryAddress.ListenSockMap[Index].ProtocolId);
|
|
|
|
ASSERT(PrimaryAddress.MasterMask->fd_count <= PrimaryAddress.MaskSize);
|
|
|
|
if (Status)
|
|
{
|
|
//
|
|
// BUGBUG must clean up connection object too.
|
|
//
|
|
|
|
// We're out of memory, abort the connection...
|
|
j = TRUE;
|
|
i = setsockopt( isock, SOL_SOCKET, SO_DONTLINGER, (const char *) &j,
|
|
sizeof(j));
|
|
|
|
ASSERT(i == 0);
|
|
|
|
i = closesocket( isock);
|
|
|
|
ASSERT(i == 0);
|
|
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
COMMON_ServerReceiveAny (
|
|
IN PADDRESS Address,
|
|
OUT PSCONNECTION * pSConnection,
|
|
OUT void PAPI * PAPI * Buffer,
|
|
OUT unsigned int PAPI * BufferLength,
|
|
IN long Timeout
|
|
)
|
|
// Read a message from any of the connections. Besides reading messages,
|
|
// new connections are confirmed and closed connections are detected. Idle
|
|
// connection processing is handled for us by I_AgeConnections. The caller
|
|
// will serialize access to this routine.
|
|
{
|
|
UNUSED (Timeout);
|
|
|
|
while (1)
|
|
{
|
|
RPC_STATUS RpcStatus;
|
|
unsigned Index;
|
|
int NumActive;
|
|
int protocolId;
|
|
|
|
//
|
|
// Find a connection with data ready to be recv-ed...
|
|
//
|
|
if (Index = FindSockWithDataReady (0))
|
|
{
|
|
PSCONNECTION SConnection;
|
|
|
|
//
|
|
// Found one. Find its Connection structure...
|
|
//
|
|
*pSConnection = SConnection
|
|
= PrimaryAddress.DataSockMap[Index].Conn;
|
|
//
|
|
// Call ServerReceive to read the data, then return to the
|
|
// runtime with it
|
|
//
|
|
|
|
if (SConnection == 0)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: Connection Deleted[?]\n");
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
protocolId = PrimaryAddress.DataSockMap[Index].ProtocolId ;
|
|
|
|
if (TransportTab[protocolId].IsDatagram)
|
|
{
|
|
ASSERT(TransportTab[protocolId].RecvFunc != NULL) ;
|
|
ASSERT(TransportTab[protocolId].protocolId == protocolId) ;
|
|
|
|
if ((* (TransportTab[protocolId].RecvFunc))
|
|
(SConnection, Buffer, BufferLength) == RPC_S_OK)
|
|
{
|
|
//
|
|
// Remove the socket from the select mask and the
|
|
// socket -> connection map, then call the receive fn.
|
|
//
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
FD_CLR(PrimaryAddress.DataSockMap[Index].Sock,PrimaryAddress.MasterMask);
|
|
memset((char *) &(PrimaryAddress.DataSockMap[Index]),
|
|
0, sizeof(SOCKMAP)) ;
|
|
|
|
if (Index == PrimaryAddress.DataMapInfo.LastEntry)
|
|
PrimaryAddress.DataMapInfo.LastEntry--;
|
|
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// BUGBUG:we can make this better by actually keeping a
|
|
// count
|
|
|
|
|
|
//
|
|
// Workaround for NT AppleTalk Stack bug. No ReceiveDirect Threads for ADSP.
|
|
//
|
|
if ((PrimaryAddress.RecvDirectPossible > 0) && (NCACN_ADSP != protocolId))
|
|
{
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
// Try and make this connection ReceiveDirect
|
|
// BUGBUG: should we be passing PrimaryAddress
|
|
if (I_RpcTransMaybeMakeReceiveDirect(SConnection->Address, SConnection))
|
|
{
|
|
unsigned i ;
|
|
int SockOpt = RECV_TIMEOUT ;
|
|
|
|
if (setsockopt( SConnection->ConnSock, SOL_SOCKET, SO_RCVTIMEO,
|
|
(char *) &SockOpt, sizeof(SockOpt) ) != 0)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: setsockopt failed: %d\n",
|
|
WSAGetLastError()) ;
|
|
ASSERT(0) ;
|
|
#endif
|
|
}
|
|
|
|
ASSERT(PrimaryAddress.DataSockMap[Index].Sock \
|
|
== SConnection->ConnSock) ;
|
|
|
|
ASSERT(SConnection->ReceiveDirectFlag == 0) ;
|
|
|
|
SConnection->ReceiveDirectFlag = 1 ;
|
|
|
|
memset((char *) &(PrimaryAddress.DataSockMap[Index]),
|
|
0, sizeof(SOCKMAP)) ;
|
|
|
|
FD_CLR(SConnection->ConnSock, PrimaryAddress.MasterMask);
|
|
|
|
if (Index == PrimaryAddress.DataMapInfo.LastEntry)
|
|
PrimaryAddress.DataMapInfo.LastEntry--;
|
|
|
|
I_RpcTransServerReceiveDirectReady(SConnection) ;
|
|
|
|
PrimaryAddress.RecvDirectPossible-- ;
|
|
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
continue;
|
|
}
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
}
|
|
|
|
ASSERT ( (protocolId >= NCACN_IP_TCP) &&
|
|
(protocolId < NCA_MAX_PROTOCOL_VALUE_PLUS_ONE)) ;
|
|
|
|
ASSERT(TransportTab[protocolId].RecvFunc != NULL) ;
|
|
ASSERT(TransportTab[protocolId].protocolId == protocolId) ;
|
|
|
|
RpcStatus = (* (TransportTab[protocolId].RecvFunc))
|
|
(SConnection, Buffer, BufferLength) ;
|
|
|
|
if ((protocolId == NCACN_IP_TCP || protocolId == NCACN_SPX) &&
|
|
RpcStatus == RPC_P_TIMEOUT)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
return RpcStatus;
|
|
}
|
|
//
|
|
// All connections caught up for now...select() for more
|
|
// data ready...
|
|
//
|
|
do
|
|
{
|
|
//
|
|
// Fill in the select() mask
|
|
//
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
memcpy (PrimaryAddress.Mask, PrimaryAddress.MasterMask,
|
|
sizeof(fd_big_set) + PrimaryAddress.MaskSize *sizeof(SOCKET));
|
|
|
|
if (PrimaryAddress.PreviousMask != 0)
|
|
{
|
|
I_RpcFree(PrimaryAddress.PreviousMask);
|
|
PrimaryAddress.PreviousMask = 0 ;
|
|
}
|
|
|
|
if (PrimaryAddress.PreviousDataMap != 0)
|
|
{
|
|
I_RpcFree(PrimaryAddress.PreviousDataMap);
|
|
PrimaryAddress.PreviousDataMap = 0 ;
|
|
}
|
|
|
|
if (PrimaryAddress.PreviousListenMap != 0)
|
|
{
|
|
I_RpcFree(PrimaryAddress.PreviousListenMap);
|
|
PrimaryAddress.PreviousListenMap = 0 ;
|
|
}
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
|
|
// there is still a faint chance of a race condition where,
|
|
// the select socket is poked before I get a chance to
|
|
// move from this statement to the select
|
|
PrimaryAddress.ThreadListening = 1 ;
|
|
//
|
|
// Wait for data...
|
|
//
|
|
NumActive = select ( 0,
|
|
(fd_set *) PrimaryAddress.Mask,
|
|
(fd_set *) 0,
|
|
(fd_set *) 0,
|
|
NULL) ;
|
|
|
|
#if DBG
|
|
if (NumActive < 0)
|
|
{
|
|
PrintToDebugger("RPCLTSCM: select ret (%d): LastErr (%d)\n",
|
|
NumActive, WSAGetLastError());
|
|
}
|
|
#endif
|
|
|
|
if(NumActive >0)
|
|
{
|
|
if(FD_ISSET(PrimaryAddress.SyncListenSock, PrimaryAddress.Mask))
|
|
{
|
|
SOCKET tempsock ;
|
|
int i ;
|
|
|
|
NumActive = 0 ;
|
|
tempsock = accept(PrimaryAddress.SyncListenSock, 0, 0) ;
|
|
|
|
if (tempsock != INVALID_SOCKET)
|
|
{
|
|
i = closesocket(PrimaryAddress.SyncListenSock) ;
|
|
ASSERT(i == 0) ;
|
|
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
RpcStatus = AddSyncSocket(tempsock) ;
|
|
FD_CLR(PrimaryAddress.SyncListenSock, PrimaryAddress.MasterMask) ;
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
PrimaryAddress.SyncListenSock = INVALID_SOCKET ;
|
|
}
|
|
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
ASSERT(0) ;
|
|
return RpcStatus ;
|
|
}
|
|
}
|
|
else if(FD_ISSET(PrimaryAddress.SyncSock, PrimaryAddress.Mask))
|
|
{
|
|
char c;
|
|
|
|
NumActive = 0;
|
|
|
|
if (recv(PrimaryAddress.SyncSock, &c, sizeof(char), SYNC_FLAGS)
|
|
== SOCKET_ERROR)
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
} while (NumActive <= 0);
|
|
|
|
//
|
|
// If there is no connect request on the listen socket, then
|
|
// break immediately...
|
|
//
|
|
while(Index = FindSockWithDataReady(1))
|
|
{
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
RpcStatus = AcceptNewConnection (Index);
|
|
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
return RpcStatus;
|
|
}
|
|
|
|
FD_CLR(PrimaryAddress.ListenSockMap[Index].Sock, PrimaryAddress.Mask);
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
RPC_STATUS ConnectToSyncSocket()
|
|
{
|
|
switch(PrimaryAddress.SyncSockType)
|
|
{
|
|
case NCACN_IP_TCP:
|
|
return TCP_ConnectToSyncSocket() ;
|
|
|
|
case NCACN_SPX:
|
|
return SPX_ConnectToSyncSocket() ;
|
|
|
|
#ifdef NTENV
|
|
case NCACN_NB_NB:
|
|
case NCACN_NB_TCP:
|
|
case NCACN_NB_IPX:
|
|
return NB_ConnectToSyncSocket();
|
|
#endif // NTENV
|
|
|
|
default:
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("RPC: invalid sync socket type %u\n",
|
|
PrimaryAddress.SyncSockType);
|
|
#endif
|
|
return (RPC_S_INTERNAL_ERROR) ;
|
|
}
|
|
}
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
TimeoutHandler(
|
|
IN PSCONNECTION SConnection
|
|
)
|
|
/*++
|
|
This routine is called when a receive direct thread times out.
|
|
Return Values:
|
|
RPC_P_TIMEOUT:
|
|
Thread has been migrated
|
|
Anything else:
|
|
Thread has not been migrated
|
|
--*/
|
|
{
|
|
int i ;
|
|
int SocketOptionsValue ;
|
|
char c ;
|
|
RPC_STATUS Status ;
|
|
int SockOpt = RECV_TIMEOUT ;
|
|
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
if (I_RpcTransMaybeMakeReceiveAny(SConnection) == 0)
|
|
{
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
return (RPC_S_OK);
|
|
}
|
|
|
|
// notify runtime about the the direct->any transition
|
|
SConnection->ReceiveDirectFlag = 0 ;
|
|
|
|
if (SConnection->ProtocolId == NCACN_IP_TCP ||
|
|
SConnection->ProtocolId == NCACN_SPX)
|
|
{
|
|
SocketOptionsValue = RECV_ANY_TIMEOUT_TCPSPX;
|
|
}
|
|
else
|
|
{
|
|
SocketOptionsValue = RECV_ANY_TIMEOUT;
|
|
}
|
|
|
|
// do the stuff neccassary
|
|
//BUGBUG: need to set the timeout, if the two timeout values need to
|
|
// be different
|
|
if (setsockopt( SConnection->ConnSock, SOL_SOCKET, SO_RCVTIMEO,
|
|
(char *) &SocketOptionsValue, sizeof(SocketOptionsValue) ) != 0)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: setsockopt failed: %d\n",
|
|
WSAGetLastError()) ;
|
|
|
|
ASSERT(0) ;
|
|
#endif
|
|
}
|
|
|
|
Status = InsertDataSocket(SConnection->Address,
|
|
FALSE,
|
|
SConnection->ConnSock,
|
|
SConnection,
|
|
SConnection->ProtocolId
|
|
);
|
|
|
|
if (Status)
|
|
{
|
|
ASSERT(Status == RPC_S_OUT_OF_MEMORY);
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: InsertDataSocketFailed\n") ;
|
|
#endif
|
|
goto cleanup;
|
|
}
|
|
|
|
PrimaryAddress.RecvDirectPossible++ ;
|
|
|
|
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
Status = PokeSyncSocket();
|
|
if (Status)
|
|
{
|
|
goto cleanup ;
|
|
}
|
|
|
|
return (RPC_P_TIMEOUT) ;
|
|
|
|
cleanup:
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
SConnection->ReceiveDirectFlag = 1 ;
|
|
|
|
// try my best to cleanup
|
|
if (DeleteDataSocket(SConnection->ConnSock) != RPC_S_OK)
|
|
{
|
|
// now we are really ...
|
|
ASSERT(0) ;
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: TimeoutHandler, couldn't delete socket\n") ;
|
|
#endif
|
|
}
|
|
|
|
I_RpcTransCancelMigration(SConnection) ;
|
|
if (setsockopt( SConnection->ConnSock, SOL_SOCKET, SO_RCVTIMEO,
|
|
(char *) &SockOpt, sizeof(SockOpt) ) != 0)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("RPCLTSCM: setsockopt failed: %d\n",
|
|
WSAGetLastError()) ;
|
|
|
|
ASSERT(0) ;
|
|
#endif
|
|
}
|
|
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
ASSERT(Status != RPC_P_TIMEOUT) ;
|
|
return Status;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
PokeSyncSocket()
|
|
{
|
|
static long firstThread = -1 ;
|
|
char c;
|
|
|
|
// if not connected to the synchronization socket, make a connection
|
|
if (PrimaryAddress.SyncClient == INVALID_SOCKET &&
|
|
InterlockedIncrement(&firstThread) == 0)
|
|
{
|
|
RPC_STATUS Status;
|
|
|
|
if ((Status = ConnectToSyncSocket()) != RPC_S_OK)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("rpcltscm.dll: connect() in PokeSyncSocket failed with %lu\n", WSAGetLastError()) ;
|
|
#endif
|
|
firstThread = -1 ;
|
|
|
|
return Status ;
|
|
}
|
|
|
|
return (RPC_S_OK) ;
|
|
}
|
|
|
|
while (PrimaryAddress.SyncClient == INVALID_SOCKET)
|
|
{
|
|
Sleep(0) ;
|
|
}
|
|
|
|
if (send(PrimaryAddress.SyncClient,
|
|
&c, sizeof(char), SYNC_FLAGS) == SOCKET_ERROR)
|
|
{
|
|
#if DBG
|
|
PrintToDebugger("rpcltscm.dll: send() in PokeSyncSocket failed with %lu\n", WSAGetLastError()) ;
|
|
#endif
|
|
return (RPC_S_OUT_OF_MEMORY) ;
|
|
}
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
MaybePokeSyncSocket(
|
|
)
|
|
{
|
|
int nIter ;
|
|
RPC_STATUS Status ;
|
|
|
|
if (PrimaryAddress.ThreadListening)
|
|
{
|
|
Status = PokeSyncSocket() ;
|
|
|
|
if (Status)
|
|
{
|
|
return Status ;
|
|
}
|
|
|
|
return RPC_S_OK ;
|
|
}
|
|
else
|
|
{
|
|
for (nIter = 0; !PrimaryAddress.ThreadListening && nIter < 500; nIter++)
|
|
{
|
|
Sleep(10) ; // deliberately sleeping for > 0
|
|
}
|
|
|
|
if (PrimaryAddress.ThreadListening)
|
|
{
|
|
Status = PokeSyncSocket() ;
|
|
|
|
if (Status)
|
|
{
|
|
return Status ;
|
|
}
|
|
|
|
return RPC_S_OK ;
|
|
}
|
|
else
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
ThreadListening(
|
|
IN PADDRESS Address
|
|
)
|
|
{
|
|
static long firstThread = -1 ;
|
|
RPC_STATUS Status ;
|
|
int i;
|
|
|
|
if (PrimaryAddress.ThreadListening == 0 &&
|
|
InterlockedIncrement(&firstThread) == 0)
|
|
{
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
for (i = 0; i < Address->iOpen ; i++)
|
|
{
|
|
Status =
|
|
AddListenSocket(Address, Address->ListenSock[i], Address->ListenSockType) ;
|
|
if (Status)
|
|
{
|
|
firstThread = -1 ;
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
return Status;
|
|
}
|
|
}
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
|
|
return (RPC_S_OK) ;
|
|
}
|
|
|
|
return RPC_P_THREAD_LISTENING ;
|
|
}
|
|
|
|
|
|
unsigned
|
|
FindSockWithDataReady (
|
|
BOOL bListenMap
|
|
)
|
|
{
|
|
unsigned i;
|
|
PSOCKMAP Map;
|
|
MAPINFO *pMapInfo ;
|
|
|
|
// It is okay to use the current DataSockMap and ListenSock map
|
|
// to search in the mask, at worst, we'll iterate a few more times
|
|
// than needed.
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
if(bListenMap)
|
|
{
|
|
Map = PrimaryAddress.ListenSockMap ;
|
|
pMapInfo = &(PrimaryAddress.ListenMapInfo) ;
|
|
}
|
|
else
|
|
{
|
|
Map = PrimaryAddress.DataSockMap;
|
|
pMapInfo = &(PrimaryAddress.DataMapInfo) ;
|
|
}
|
|
//
|
|
// We make two passes here, if necessary. This is because there is
|
|
// a bitfield in which 1's correspond to sockets on which there is
|
|
// data to be read. If we started from the same bit each time looking
|
|
// for the first 1, then that socket would get all of the attention,
|
|
// and those further down the line would increasingly suffer from
|
|
// the "I'll only look at you if noone else needs attention"
|
|
// syndrome. So we keep track of where we found data last time,
|
|
// and start looking just beyond it next time. At the last entry,
|
|
// we wrap around and go into pass 2.
|
|
//
|
|
//
|
|
// First Pass scan...
|
|
//
|
|
for (i = pMapInfo->StartEntry; i <= pMapInfo->LastEntry; i++)
|
|
{
|
|
if ( FD_ISSET (Map[i].Sock, PrimaryAddress.Mask))
|
|
{
|
|
|
|
FD_CLR ( Map[i].Sock, PrimaryAddress.Mask );
|
|
if (i == pMapInfo->LastEntry)
|
|
pMapInfo->StartEntry = 1;
|
|
else
|
|
pMapInfo->StartEntry = i + 1;
|
|
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
return (i);
|
|
}
|
|
}
|
|
//
|
|
// Second Pass Scan...
|
|
//
|
|
for (i = 1; i < pMapInfo->StartEntry ; i++)
|
|
{
|
|
if (FD_ISSET (Map[i].Sock, PrimaryAddress.Mask))
|
|
{
|
|
FD_CLR ( Map[i].Sock, PrimaryAddress.Mask);
|
|
|
|
if (i == pMapInfo->LastEntry)
|
|
pMapInfo->StartEntry = 1;
|
|
else
|
|
pMapInfo->StartEntry = i + 1;
|
|
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
return (i);
|
|
}
|
|
}
|
|
//
|
|
// No data ready
|
|
//
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
return(0);
|
|
}
|
|
|
|
|
|
RPC_SERVER_TRANSPORT_INFO *
|
|
TransportLoad (
|
|
IN RPC_CHAR * RpcProtocolSequence
|
|
)
|
|
{
|
|
WSADATA WsaData;
|
|
TRANSTAB *tabPtr ;
|
|
RPC_SERVER_TRANSPORT_INFO *TransInfo ;
|
|
int retval ;
|
|
int justInitialized = 0;
|
|
int Status ;
|
|
|
|
UNUSED(RpcProtocolSequence);
|
|
|
|
if (!initialized)
|
|
{
|
|
RpcTryExcept
|
|
{
|
|
Status = WSAStartup( 0x0101, &WsaData ) ;
|
|
}
|
|
RpcExcept( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ASSERT(!"RPC: WSAStartup threw an exception\n") ;
|
|
Status = ERROR_OUTOFMEMORY ;
|
|
}
|
|
RpcEndExcept
|
|
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
PrimaryAddress.SyncSockType = -1 ;
|
|
PrimaryAddress.SyncListenSock = INVALID_SOCKET ;
|
|
PrimaryAddress.SyncPort = 0;
|
|
justInitialized = 1;
|
|
}
|
|
|
|
for (tabPtr = TransportTab; tabPtr->RpcProtocolSequence != NULL; tabPtr++)
|
|
{
|
|
if (RpcpStringCompare(RpcProtocolSequence, tabPtr->RpcProtocolSequence) == 0)
|
|
{
|
|
TransInfo = (*(tabPtr->TransFunc))(tabPtr->protocolId) ;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (0 == initialized)
|
|
{
|
|
goto cleanup ;
|
|
}
|
|
else
|
|
{
|
|
if (justInitialized)
|
|
{
|
|
if (0 == InitializePrimaryAddress())
|
|
{
|
|
initialized = 0;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TransInfo ;
|
|
|
|
cleanup:
|
|
WSACleanup();
|
|
closesocket(PrimaryAddress.SyncListenSock);
|
|
PrimaryAddress.SyncSockType = -1 ;
|
|
PrimaryAddress.SyncListenSock = INVALID_SOCKET ;
|
|
PrimaryAddress.SyncPort = 0;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
#ifdef NTENV
|
|
|
|
DWORD
|
|
InitializeCriticalSectionWrapper(
|
|
RTL_CRITICAL_SECTION * Mutex
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
|
|
NtStatus = RtlInitializeCriticalSection(Mutex);
|
|
|
|
return RtlNtStatusToDosError(NtStatus);
|
|
}
|
|
#else
|
|
|
|
DWORD
|
|
InitializeCriticalSectionWrapper(
|
|
CRITICAL_SECTION * Mutex
|
|
)
|
|
{
|
|
DWORD Status = RPC_S_OK;
|
|
|
|
__try
|
|
{
|
|
InitializeCriticalSection(Mutex);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
#endif
|
|
|
|
|
|
BOOL
|
|
InitializePrimaryAddress(
|
|
)
|
|
{
|
|
|
|
if (InitializeCriticalSectionWrapper(&PrimaryAddress.TransCritSec))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
PrimaryAddress.NumConnections = 0;
|
|
PrimaryAddress.RecvDirectPossible = 0;
|
|
PrimaryAddress.SyncSock = INVALID_SOCKET ;
|
|
PrimaryAddress.SyncClient = INVALID_SOCKET ;
|
|
PrimaryAddress.ThreadListening = 0 ;
|
|
PrimaryAddress.PreviousMask = 0 ;
|
|
PrimaryAddress.PreviousListenMap = 0;
|
|
PrimaryAddress.PreviousDataMap = 0;
|
|
|
|
// add listen socket to listen socket list
|
|
|
|
PrimaryAddress.MasterMask = I_RpcAllocate(sizeof(fd_big_set) +
|
|
INITIAL_MASK_SIZE * sizeof(SOCKET));
|
|
|
|
PrimaryAddress.Mask = I_RpcAllocate(sizeof(fd_big_set) +
|
|
INITIAL_MASK_SIZE * sizeof(SOCKET));
|
|
|
|
PrimaryAddress.DataSockMap =
|
|
I_RpcAllocate(INITIAL_MAPSIZE * sizeof(SOCKMAP));
|
|
|
|
PrimaryAddress.ListenSockMap = I_RpcAllocate(INITIAL_MAPSIZE *
|
|
sizeof(SOCKMAP)) ;
|
|
|
|
if ( (PrimaryAddress.DataSockMap == (SOCKMAP *) 0)
|
|
|| (PrimaryAddress.MasterMask == (fd_big_set *) 0)
|
|
|| (PrimaryAddress.Mask == (fd_big_set *) 0)
|
|
|| (PrimaryAddress.ListenSockMap == (SOCKMAP *) 0))
|
|
{
|
|
if (PrimaryAddress.DataSockMap) I_RpcFree(PrimaryAddress.DataSockMap);
|
|
if (PrimaryAddress.MasterMask) I_RpcFree(PrimaryAddress.MasterMask);
|
|
if (PrimaryAddress.Mask) I_RpcFree(PrimaryAddress.Mask);
|
|
if (PrimaryAddress.ListenSockMap) I_RpcFree(PrimaryAddress.ListenSockMap) ;
|
|
|
|
return 0;
|
|
}
|
|
|
|
PrimaryAddress.MaskSize = INITIAL_MASK_SIZE;
|
|
|
|
FD_ZERO(PrimaryAddress.MasterMask);
|
|
FD_ZERO(PrimaryAddress.Mask);
|
|
|
|
PrimaryAddress.DataMapInfo.StartEntry = 1;
|
|
PrimaryAddress.DataMapInfo.LastEntry = 0;
|
|
PrimaryAddress.DataMapInfo.MaxEntries = INITIAL_MAPSIZE;
|
|
memset ( PrimaryAddress.DataSockMap, 0, (INITIAL_MAPSIZE * sizeof (SOCKMAP)));
|
|
|
|
PrimaryAddress.ListenMapInfo.StartEntry = 1 ;
|
|
PrimaryAddress.ListenMapInfo.LastEntry = 0 ;
|
|
PrimaryAddress.ListenMapInfo.MaxEntries = INITIAL_MAPSIZE;
|
|
memset ( PrimaryAddress.ListenSockMap, 0, (INITIAL_MAPSIZE * sizeof (SOCKMAP)));
|
|
|
|
/*
|
|
Prevent this slot from getting picked up by a connection..
|
|
*/
|
|
PrimaryAddress.DataSockMap[0].Sock = (SOCKET) -1;
|
|
PrimaryAddress.ListenSockMap[0].Sock = (SOCKET) -1 ;
|
|
|
|
FD_BIG_SET(PrimaryAddress.SyncListenSock, PrimaryAddress) ;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
CONN_StartListening(
|
|
IN PADDRESS Address
|
|
)
|
|
{
|
|
RPC_STATUS Status ;
|
|
int i ;
|
|
|
|
EnterCriticalSection(&PrimaryAddress.TransCritSec) ;
|
|
|
|
for (i = 0; i < Address->iOpen ; i++)
|
|
{
|
|
|
|
Status =
|
|
AddListenSocket(Address, Address->ListenSock[i],
|
|
Address->ListenSockType) ;
|
|
|
|
if (Status)
|
|
{
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
return Status;
|
|
}
|
|
|
|
|
|
}
|
|
LeaveCriticalSection(&PrimaryAddress.TransCritSec);
|
|
|
|
return MaybePokeSyncSocket() ;
|
|
}
|
|
|