📄 scsman.cxx
字号:
if ((ul_wins_report[i] == INADDR_NONE) || (ul_wins_report[i] == ul_addr))
fFound = TRUE;
else {
for (int j = 0 ; j < i ; ++j) {
if (ul_wins_report[j] == ul_wins_report[i]) {
fFound = TRUE;
break;
}
}
}
if (! fFound) {
sin.sin_addr.S_un.S_addr = ul_wins_report[i];
ipPeerAddr = sin.sin_addr;
if ((iPass == 0) && ping (ul_wins_report[i])) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Connecting to %s as %d.%d.%d.%d (WINS lookup, ping)\n", lpszHostName,
sin.sin_addr.S_un.S_un_b.s_b1, sin.sin_addr.S_un.S_un_b.s_b2, sin.sin_addr.S_un.S_un_b.s_b3, sin.sin_addr.S_un.S_un_b.s_b4);
#endif
return connect (s, (sockaddr *)&sin, sizeof(sin)) == 0;
}
if ((iPass == 1) || (! gMachine->uiPingPort)) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Connecting to %s as %d.%d.%d.%d (WINS lookup)\n", lpszHostName,
sin.sin_addr.S_un.S_un_b.s_b1, sin.sin_addr.S_un.S_un_b.s_b2, sin.sin_addr.S_un.S_un_b.s_b3, sin.sin_addr.S_un.S_un_b.s_b4);
#endif
if (connect (s, (sockaddr *)&sin, sizeof(sin)) == 0)
return TRUE;
}
}
}
if (! gMachine->uiPingPort)
break;
}
return FALSE;
}
//
// Reading thread: establish the connection and start recv'ing
// Writing thread: control timely establishment of connection and then
// monitor situation and send stuff.
//
// Finally, writing thread brings down reading thread, decrements thread
// pair count and exits.
//
void ScSession::ServiceThreadR (void) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Started receive thread for %s\n", lpszHostName);
#endif
if (fSessionState != SCSESSION_STATE_CONNECTING)
return;
InitConnection ();
if (s == INVALID_SOCKET) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Creating socket connection for %s\n", lpszHostName);
#endif
//
// Create socket.
//
s = socket (AF_INET, SOCK_STREAM, 0);
if ((s == INVALID_SOCKET) || (! Connect ())) {
#if defined (SC_VERBOSE)
if (s == INVALID_SOCKET)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Can't open a socket for %s\n", lpszHostName);
else
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Can't connect to %s\n", lpszHostName);
#endif
gMem->Lock ();
FailConnection ();
SetEvent (hEvent);
CloseHandle (hServiceThreadR);
hServiceThreadR = NULL;
gMem->Unlock ();
return;
}
gMem->Lock ();
OkConnection (SCSESSION_STATE_CONNECTED_CLIENT);
gMem->Unlock ();
//
// Send establish connection packet
//
if ((! SendECP(FALSE)) || (! RecvECP())) {
gMem->Lock ();
FailConnection ();
SetEvent (hEvent);
CloseHandle (hServiceThreadR);
hServiceThreadR = NULL;
gMem->Unlock ();
return;
}
//
// Get ack.
//
if ((! SendCPP()) || (! RecvCPP())) {
gMem->Lock ();
FailConnection ();
SetEvent (hEvent);
CloseHandle (hServiceThreadR);
hServiceThreadR = NULL;
gMem->Unlock ();
return;
}
} else {
gMem->Lock ();
OkConnection (SCSESSION_STATE_CONNECTED_SERVER);
gMem->Unlock ();
//
// Receive establishing connection packet.
//
if ((! RecvECP()) || (! SendECP(FALSE))) {
gMem->Lock ();
FailConnection ();
SetEvent (hEvent);
CloseHandle (hServiceThreadR);
hServiceThreadR = NULL;
gMem->Unlock ();
return;
}
//
// Send ack
//
if ((! RecvCPP()) || (! SendCPP())) {
gMem->Lock ();
FailConnection ();
SetEvent (hEvent);
CloseHandle (hServiceThreadR);
hServiceThreadR = NULL;
gMem->Unlock ();
return;
}
}
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Session with %s initialized successfully\n", lpszHostName);
#endif
fSessionState = SCSESSION_STATE_OPERATING;
SetEvent (hEvent);
while (fSessionState == SCSESSION_STATE_OPERATING) {
const int iHeaderSize = sizeof(CBaseHeader);
const int iBufferSize = sizeof (CBaseHeader) + sizeof (CDebugSection) + sizeof(CSessionSection) +
sizeof (CECSection) + sizeof (CCPSection) + sizeof (CInternalSection);
char __buf[iBufferSize];
ScPacketImage *pImage = NULL;
char *pcBuffer = NULL;
int fError = FALSE;
int iTotalRecvd = 0;
while (iTotalRecvd < iHeaderSize) {
int iRecvd = recv (s, &__buf[iTotalRecvd], iHeaderSize - iTotalRecvd, 0);
if (iRecvd <= 0) {
fError = TRUE;
break;
}
iTotalRecvd += iRecvd;
}
if (fError) {
// The other side had just closed cconnection. If we are not done and are writing,
// the writer thread will error out. Otherwise, we just become inactive...
if ((iTotalRecvd == 0) && (fSessionState == SCSESSION_STATE_OPERATING)) {
fSessionState = SCSESSION_STATE_INACTIVE;
break;
}
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Error receiving a packet from %s (%d bytes received)\n", lpszHostName, iTotalRecvd);
#endif
break;
}
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Received a packet from %s\n", lpszHostName);
#endif
CBaseHeader *pBaseHeader = (CBaseHeader *)__buf;
if (! (pBaseHeader->SignatureIsValid() && pBaseHeader->VersionIsValid())) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Bad packet from %s: incorrect version or signature\n", lpszHostName);
#endif
break;
}
int iPacketSize; // Has to be multiple of 4 and more than just header
if (((iPacketSize = pBaseHeader->GetPacketSize()) <= iHeaderSize) ||
(iPacketSize & 3)) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Bad packet from %s: too small (%d bytes)\n", lpszHostName, iPacketSize);
#endif
break;
}
CSessionSection *pcSessionSection = NULL;
int iTotalSize = iPacketSize;
if (pBaseHeader->GetType() != FALCON_INTERNAL_PACKET) {
iTotalSize += (pBaseHeader->SessionIsIncluded() ? CSessionSection::CalcSectionSize(): 0);
pImage = (ScPacketImage *)g_funcAlloc (sizeof (*pImage) + iTotalSize, g_pvAllocData);
if (! pImage)
break;
gMem->Lock ();
++gSessionMan->fBusy;
gMem->Unlock ();
memset (&pImage->sect, 0, sizeof(pImage->sect));
memset (&pImage->ucSourceAddr, 0, sizeof(pImage->ucSourceAddr));
pImage->allflags = 0;
pImage->flags.fSecureSession = ! gMachine->fUntrustedNetwork;
pImage->hkOrderKey = 0;
pImage->ipSourceAddr = ipPeerAddr;
pImage->pvBinary = NULL;
pImage->pvExt = NULL;
void *pvBinaryStart = ((char *)pImage + sizeof(*pImage));
memcpy (pvBinaryStart, __buf, iHeaderSize);
pImage->flags.fHaveIpv4Addr = TRUE;
pBaseHeader = (CBaseHeader *)pvBinaryStart;
pcBuffer = (char *)pBaseHeader;
if (pBaseHeader->SessionIsIncluded())
pcSessionSection = (CSessionSection *)(pcBuffer + iPacketSize);
} else
pcBuffer = __buf;
while (iTotalRecvd < iTotalSize) {
int iRecvd = recv (s, &pcBuffer[iTotalRecvd], iTotalSize - iTotalRecvd, 0);
if (iRecvd <= 0) {
fError = TRUE;
break;
}
iTotalRecvd += iRecvd;
}
if (fError) {
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Error receiving a packet from %s (%d bytes out of %d received)\n", lpszHostName, iTotalRecvd, iTotalSize);
#endif
if (pImage) {
g_funcFree (pImage, g_pvFreeData);
gMem->Lock ();
--gSessionMan->fBusy;
gMem->Unlock ();
}
break;
}
gMem->Lock ();
int fRes;
if (pImage) {
fRes = HandleUserPacket (pImage, pcSessionSection);
--gSessionMan->fBusy;
} else
fRes = HandleInternalPacket (pBaseHeader);
gMem->Unlock ();
if (! fRes)
break;
}
if (fSessionState == SCSESSION_STATE_EXITING)
return;
gMem->Lock ();
if (fSessionState == SCSESSION_STATE_OPERATING)
FailConnection ();
CloseHandle (hServiceThreadR);
hServiceThreadR = NULL;
SetEvent (hEvent); // Thread exited
gMem->Unlock ();
}
void ScSession::ReturnUnacketPacketsToQueues(void) {
//
// Unacked packets return to the respective queues...
//
while (pSentPackets) {
SentPacket *pSentNext = pSentPackets->pNext;
SVSUTIL_ASSERT (! pSentPackets->pPacket->pQueue->qp.bIsIncoming);
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Returning express unacked message %08x ptr %08x to %s\n", pSentPackets->pPacket->uiMessageID, pSentPackets->pPacket, pSentPackets->pPacket->pQueue->lpszFormatName);
#endif
pSentPackets->pPacket->pQueue->InsertPacket (pSentPackets->pPacket);
svsutil_FreeFixed (pSentPackets, gMem->pAckNodeMem);
pSentPackets = pSentNext;
}
while (pSentRelPackets) {
SentPacket *pSentNext = pSentRelPackets->pNext;
SVSUTIL_ASSERT (! pSentRelPackets->pPacket->pQueue->qp.bIsIncoming);
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Returning reliable unacked message %08x ptr %08x to %s\n", pSentRelPackets->pPacket->uiMessageID, pSentRelPackets->pPacket, pSentRelPackets->pPacket->pQueue->lpszFormatName);
#endif
pSentRelPackets->pPacket->pQueue->InsertPacket (pSentRelPackets->pPacket);
svsutil_FreeFixed (pSentRelPackets, gMem->pAckNodeMem);
pSentRelPackets = pSentNext;
}
}
void ScSession::FinishSession (void) {
SVSUTIL_ASSERT (gMem->IsLocked ());
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Finishing session...\n");
#endif
int fSessStateSav = fSessionState;
fSessionState = SCSESSION_STATE_EXITING; // Temporarily so that it will exit without locking
ipPeerAddr.S_un.S_addr = INADDR_NONE;
if (s != INVALID_SOCKET) {
closesocket (s);
s = INVALID_SOCKET;
}
if (hServiceThreadR) {
if (WaitForSingleObject (hServiceThreadR, SC_THREAD_WAIT2) == WAIT_TIMEOUT) {
scerror_Inform (MSMQ_SC_ERRMSG_READERKILLED, lpszHostName);
TerminateThread (hServiceThreadR, 0);
}
CloseHandle (hServiceThreadR);
}
hServiceThreadR = NULL;
fSessionState = fSessStateSav;
if (gMachine->fUseSRMP)
SRMPCloseSession();
gSessionMan->ReleaseThreadPair ();
CloseHandle (hEvent);
hEvent = NULL;
CloseHandle (hServiceThreadW);
hServiceThreadW = NULL;
memset (&guidDest, 0, sizeof(guidDest));
uiConnectionStamp = 0;
uiAckTimeout = 0;
uiStoreAckTimeout = 0;
uiMyWindowSize = 0;
uiOtherWindowSize = 0;
ReturnUnacketPacketsToQueues();
SVSUTIL_ASSERT (! pSentPackets);
SVSUTIL_ASSERT (! pSentRelPackets);
}
int ScSession::MakeSessionSect (CSessionSection *pSessSect, ScPacket *pPacket, int fForce) {
SVSUTIL_ASSERT (sessnum_greater_equal (usRelPacketsReceived, usLastRelAckSent));
unsigned short usRelFirstUnacked = usLastRelAckSent + 1;
if (! usRelFirstUnacked)
++usRelFirstUnacked;
int iRelPacketsToAck = (signed short)((signed short)usRelPacketsReceived - (signed short)usRelFirstUnacked + 1);
if (iRelPacketsToAck > STORED_ACK_BITFIELD_SIZE)
iRelPacketsToAck = STORED_ACK_BITFIELD_SIZE;
unsigned int uiRelBitMask = (iRelPacketsToAck < 2) ? 0 : ~((-1) << (iRelPacketsToAck - 1));
pSessSect->CSessionSection::CSessionSection(usPacketsReceived, iRelPacketsToAck ? usRelFirstUnacked : 0, uiRelBitMask,
usPacketsSent, usRelPacketsSent, uiMyWindowSize);
int iPacketSize = 0;
if (pPacket)
iPacketSize = pPacket->pImage->sect.pBaseHeader->GetPacketSize();
if ((fForce) || ((uiAckDue && time_greater_equal (GetTickCount(), uiAckDue)) ||
sessnum_greater_equal (usPacketsReceived, (unsigned short)(usLastAckSent + uiOtherWindowSize)) ||
sessnum_greater_equal (usRelPacketsReceived, (unsigned short)(usLastRelAckSent + STORED_ACK_BITFIELD_SIZE)))) {
if (pPacket) {
pPacket->pImage->sect.pBaseHeader->IncludeSession(TRUE);
iPacketSize += CSessionSection::CalcSectionSize();
}
usLastAckSent = usPacketsReceived;
usLastRelAckSent = usRelFirstUnacked + iRelPacketsToAck - 1;
if (usLastRelAckSent == usRelPacketsReceived) {
uiAckDue = 0;
svsutil_ClearAttrTimer (gMem->pTimer, (SVSHandle)hEvent);
}
}
return iPacketSize;
}
int ScSession::SendAck (void) {
for ( ; ; ) {
SVSUTIL_ASSERT (gMem->IsLocked ());
if (((! uiAckDue) || time_less (GetTickCount(), uiAckDue)) &&
sessnum_less (usPacketsReceived, (unsigned short)(usLastAckSent + uiOtherWindowSize)) &&
sessnum_less (usRelPacketsReceived, (unsigned short)(usLastRelAckSent + STORED_ACK_BITFIELD_SIZE)))
return TRUE;
#if defined (SC_VERBOSE)
scerror_DebugOut (VERBOSE_MASK_SESSION, L"Sending ACK for %d(%d)th packet(s) for %s\n", usPacketsReceived, usRelPacketsReceived, lpszHostName);
#endif
const int iPacketSize = sizeof(CBaseHeader) + sizeof(CInternalSection) + sizeof(CSessionSection);
char __buf[iPacketSize];
CBaseHeader *pBase = (CBaseHeader *)__buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -