468 lines
10 KiB
C++
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|