windows-nt/Source/XPSP1/NT/net/homenet/alg/alg_icq/icqprx.cpp
2020-09-26 16:20:57 +08:00

468 lines
10 KiB
C++

/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
Abstract:
Author:
Savas Guven (savasg) 27-Nov-2000
Revision History:
*/
#include "stdafx.h"
CLIST g_IcqClientList;
CSockDispatcher * g_IcqPeerDispatcherp = NULL;
IcqPrx::IcqPrx()
:m_Socketp(NULL),
m_ControlChannelp(NULL)
{
ICQ_TRC(TM_IO, TL_DUMP, (" ICQPRX - Default - Constructor"));
g_IcqComponentReferencep = dynamic_cast<PCOMPONENT_SYNC>(this);
}
IcqPrx::~IcqPrx()
{
ICQ_TRC(TM_IO, TL_DUMP, ("ICQPRX - ~ DESTRUCTOR"));
if(this->bCleanupCalled is FALSE)
{
IcqPrx::ComponentCleanUpRoutine();
}
this->bCleanupCalled = FALSE;
}
//
// The Local Socket is a resource which needs to be freed up.
// All the Clients needs to be deleted from the entries?
// The CSockDispatcher needs to be cleared up.
//
void
IcqPrx::ComponentCleanUpRoutine(void)
{
if( m_Socketp )
{
DELETE_COMPONENT( m_Socketp );
m_Socketp = NULL;
}
if( g_IcqPeerDispatcherp )
{
DELETE_COMPONENT( g_IcqPeerDispatcherp );
}
if ( m_ControlChannelp )
{
m_ControlChannelp->Cancel();
m_ControlChannelp->Release();
m_ControlChannelp = NULL;
}
this->bCleanupCalled = TRUE;
}
void
IcqPrx::StopSync()
{
ULONG hr = S_OK;
if( m_Socketp )
{
STOP_COMPONENT( m_Socketp );
}
if( g_IcqPeerDispatcherp )
{
STOP_COMPONENT( g_IcqPeerDispatcherp );
}
if( m_ControlChannelp )
{
hr = m_ControlChannelp->Cancel();
if( FAILED(hr) )
{
ICQ_TRC(TM_PRX, TL_ERROR,
("** !! Can't cancel the PRIMARY redirect e(%X)", hr));
}
else
{
m_ControlChannelp = NULL;
}
}
}
ULONG
IcqPrx::RunIcq99Proxy(
ULONG BoundaryIp
)
/*++
Routine Description:
Arguments:
none.
Return Value:
--*/
{
ULONG hr = S_OK;
USHORT port;
ULONG ip;
ICQ_TRC(TM_PRX, TL_INFO, ("> ICQ 99 PRxY %lu", BoundaryIp));
ASSERT(BoundaryIp != 0);
NEW_OBJECT( m_Socketp, CNhSock );
if( m_Socketp is NULL) return E_OUTOFMEMORY;
//
// Get the Public IP information
ip = BoundaryIp;
g_MyPublicIp = ip;
// __asm int 3
do
{
// Init globals
__try
{
g_IcqPeerDispatcherp = new CSockDispatcher(ip, 0);
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
delete g_IcqPeerDispatcherp;
hr = E_OUTOFMEMORY;
g_IcqPeerDispatcherp = NULL;
}
if ( g_IcqPeerDispatcherp is NULL )
{
ICQ_TRC(TM_PRX, TL_ERROR,("Dispatcher creation failed - mem alloc"));
hr = E_OUTOFMEMORY;
break;
}
//
// Create UDP socket with the given IP:Port in the argv
//
hr = m_Socketp->NhCreateDatagramSocket(ip, 0, NULL);
if ( hr )
{
hr = HRESULT_FROM_WIN32( hr );
ICQ_TRC(TM_PRX, TL_ERROR,
("Can't Create the Primary UDP socket E(%X)", hr));
break;
}
m_Socketp->NhQueryLocalEndpointSocket( NULL, &port );
//
// Create Dynamic SRC redirection to the IP and port
//
hr = g_IAlgServicesp->CreatePrimaryControlChannel(eALG_UDP,
ICQ99_SERVER_PORT,
eALG_DESTINATION_CAPTURE,
FALSE,
ip,
port,
&m_ControlChannelp);
if( FAILED(hr) )
{
ICQ_TRC(TM_PRX, TL_ERROR,
("ERROR !!> DynamicPortRedirect Has Failed E(%X)", hr));
break;
}
ICQ_TRC(TM_PRX, TL_INFO,
("All Outgoing redirects will be sent to %s(%hu)",
INET_NTOA(ip), htons(port)));
// Issue a read operation on the UDP socket.
hr = m_Socketp->NhReadDatagramSocket(g_IcqComponentReferencep,
NULL,
IcqReadClientUdpCompletionRoutine,
NULL,
NULL);
if ( hr )
{
hr = HRESULT_FROM_WIN32( hr );
ICQ_TRC(TM_PRX, TL_ERROR, ("hr Level E(%X)", hr));
ASSERT( FALSE );
}
} while (0);
//
// Handle the error case
//
if ( FAILED(hr) )
{
//
// Delete Dispatcher
if ( g_IcqPeerDispatcherp != NULL )
{
DELETE_COMPONENT( g_IcqPeerDispatcherp );
g_IcqPeerDispatcherp = NULL;
}
//
// Delete Socket
if ( m_Socketp != NULL )
{
DELETE_COMPONENT( m_Socketp );
m_Socketp = NULL;
}
//
// Delete The Primary Control Channel
if ( m_ControlChannelp )
{
m_ControlChannelp->Cancel();
m_ControlChannelp->Release();
m_ControlChannelp = NULL;
}
}
return hr;
}
ULONG
IcqPrx::ReadFromClientCompletionRoutine
(
ULONG ErrorCode,
ULONG BytesTransferred,
PNH_BUFFER Bufferp
)
/*++
Routine Description:
This is the READ - DISPATCHER for the UDP
Clients sending packets to the server will be caught here..
it will dispatch the packet to the appropriate ICQ client objects READER
Arguments:
none.
Return Value:
--*/
{
PCNhSock Socketp = Bufferp->Socketp;
PICQ_CLIENT IcqClientp = NULL;
// NAT_KEY_SESSION_MAPPING_EX_INFORMATION Key;
// ULONG Length = sizeof(NAT_KEY_SESSION_MAPPING_EX_INFORMATION);
ULONG hr = NO_ERROR;
ULONG LocalIp, ActualClientIp, ActualDestinationIp;
USHORT LocalPort, ActualClientPort, ActualDestinationPort;
if(ErrorCode)
{
//
// Delete the List of the Clients here.
// Starts from the head of the List
// Don't try to use a Removed Element unless you're damn sure
// that its Ref Count hasn't reached zero yet.
//
ICQ_TRC(TM_PRX, TL_CRIT, ("STOPPING the MAIN READ Socket for UDP"));
for(IcqClientp = dynamic_cast<PICQ_CLIENT>(g_IcqClientList.RemoveSortedKeys(0,0));
IcqClientp != NULL;
IcqClientp = dynamic_cast<PICQ_CLIENT>(g_IcqClientList.RemoveSortedKeys(0,0))
)
{
// NOTE: decide what to do.
}
hr = E_FAIL;
}
else
{
//
// Read about the local client..
//
// Socketp->NhQueryLocalEndpointSocket(&LocalIp, &LocalPort);
ActualClientIp = Bufferp->ReadAddress.sin_addr.S_un.S_addr;
ActualClientPort = Bufferp->ReadAddress.sin_port;
//
// Get Information about the actual destination
//
hr = m_ControlChannelp->GetOriginalDestinationInformation(ActualClientIp,
ActualClientPort,
&ActualDestinationIp,
&ActualDestinationPort,
NULL);
if( FAILED(hr) )
{
ICQ_TRC(TM_PRX, TL_ERROR,
("Can't use the GetOriginalDestination Information Interface E(%X)", hr ));
}
else
{
ICQ_TRC(TM_PRX, TL_TRACE,("DATA CAME from %s-%hu",
INET_NTOA(ActualClientIp), htons(ActualClientPort)));
ICQ_TRC(TM_PRX, TL_TRACE,("DATA WILL BE SEND TO %s-%hu",
INET_NTOA(ActualDestinationIp), htons(ActualDestinationPort)));
}
//
// Find the appropriate ICQ client entry for this
// ICQ CLIENT ~ ICQ SERVER UDP connection
// Search the Created ICQ Client List to handle proper one.
//
// NOTE: Should we handle this with just IPs?
// and the other Key might just be the server IP???
//
IcqClientp = dynamic_cast<PICQ_CLIENT>
(g_IcqClientList.SearchNodeKeys(ActualClientIp, 0));
//
// If there is no such entry than create one.
//
if(IcqClientp is NULL)
{
ICQ_TRC(TM_PRX, TL_INFO, ("PRX> NEW ICQ CLIENT DETECTED %s",
INET_NTOA(ActualClientIp)));
NEW_OBJECT(IcqClientp, ICQ_CLIENT);
//
// NOTE : ERROR CASE - proper handling pls.
if(IcqClientp is NULL)
{
ICQ_TRC(TM_PRX, TL_ERROR, ("PRX> MEMORY ALLOC ERROR"));
hr = E_OUTOFMEMORY;
return hr;
}
//
// Write the IP-PORT information Here The client class
// will collect rest of the information along the way
//
hr = IcqClientp->Initialize(Bufferp,
ActualClientIp,
ActualClientPort,
ActualDestinationIp,
ActualDestinationPort,
Socketp);
_ASSERT( SUCCEEDED(hr) );
if( FAILED(hr) )
{
DELETE_COMPONENT( IcqClientp );
}
else // Add the client to the List
{
g_IcqClientList.InsertSorted(IcqClientp);
}
}
else
{
ICQ_TRC(TM_PRX, TL_TRACE,
("PRX> ICQ CLIENT EXISTS - READ-client will be called"));
hr = IcqClientp->ClientRead( Bufferp,
ActualDestinationIp,
ActualDestinationPort );
}
}
if ( FAILED(hr) )
{
}
return hr;
}