#include "stdafx.h" VOID IcqWriteCompletionRoutine ( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp ) /*++ Routine Description: A generic Write Completion Routine. Arguments: none. Return Value: --*/ { PCNhSock Socketp = Bufferp->Socketp; ICQ_TRC(TM_IO, TL_DUMP, ("-- WRITE COMPLETION ROUTINE --")); NhReleaseBuffer(Bufferp); //Dereference Interface; DEREF_COMPONENT( Socketp, eRefIoWrite); DEREF_COMPONENT( g_IcqComponentReferencep, eRefIoWrite); } VOID ReadServerCompletionRoutine ( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp ) /*++ Routine Description: Reads the Server Responses to Client packets and then multiplexes this responses to the approprate client which was given in the Context information Arguments: none. Return Value: --*/ { PICQ_CLIENT IcqClientp = NULL; PCNhSock Socketp = NULL; ULONG Error = NO_ERROR; ICQ_TRC(TM_IO, TL_ERROR, (" ")); PROFILER(TM_IO, TL_TRACE, ("> UDP-SERVER - READ ")); if(Bufferp is NULL) return; // // Get the Client Information Socketp = Bufferp->Socketp; IcqClientp = (PICQ_CLIENT)Bufferp->Context; ASSERT(IcqClientp != NULL); if(ErrorCode) { // Re-issue a read operation if it is not critical Error. ICQ_TRC(TM_IO, TL_ERROR, ("** !! READ ERROR in Server -> Client (UDP) !! **")); NhReleaseBuffer(Bufferp); //ErrorOut(); } else // we need the context information { // // reissue read first // REF_COMPONENT( IcqClientp, eRefIoRead ); Error = Socketp->NhReadDatagramSocket(g_IcqComponentReferencep, NULL, ReadServerCompletionRoutine, IcqClientp, NULL); if(Error) { ICQ_TRC(TM_IO, TL_ERROR, ("READ ERROR")); DEREF_COMPONENT( IcqClientp, eRefIoRead ); } // multiplex the data Error = IcqClientp->ServerRead(Bufferp, 0, 0); if(Error) { NhReleaseBuffer( Bufferp ); } } // DEREFERENCING DEREF_COMPONENT( Socketp, eRefIoRead ); DEREF_COMPONENT( g_IcqComponentReferencep, eRefIoRead ); DEREF_COMPONENT( IcqClientp, eRefIoRead ); } VOID IcqReadClientUdpCompletionRoutine ( 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; ULONG Error = NO_ERROR; // HANDLE DynamicRedirectHandle = (HANDLE) Bufferp->Context; ICQ_TRC(TM_IO, TL_ERROR, (" ")); PROFILER(TM_IO, TL_TRACE,("UDP-CLIEN-READ DATA CAME from %s e(%hu)", INET_NTOA(Bufferp->ReadAddress.sin_addr.S_un.S_addr), ErrorCode)); do { if(ErrorCode) { // Re-issue a read operation if it is not critical Error. ICQ_TRC(TM_IO, TL_ERROR, ("** !! CLIENT~SERVER READ ERROR - Deletin all the Client Entries")); Error = g_IcqPrxp->ReadFromClientCompletionRoutine(ErrorCode, BytesTransferred, Bufferp); break; } else { // Re-issue a read operation. Error = Socketp->NhReadDatagramSocket(g_IcqComponentReferencep, NULL, IcqReadClientUdpCompletionRoutine, NULL,// DynamicRedirectHandle, NULL); if(Error) { ICQ_TRC(TM_IO, TL_ERROR,("TREAD !!> REISsUE READ ERROR ")); break; } g_IcqPrxp->ReadFromClientCompletionRoutine(ErrorCode, BytesTransferred, Bufferp); } // else for if (ErrorCode) } while ( FALSE ); DEREF_COMPONENT( Socketp, eRefIoRead); DEREF_COMPONENT( g_IcqComponentReferencep, eRefIoRead); } // // CLIENT - RELATED IO COMPLETION ROUTINES // VOID IcqPeerConnectionCompletionRoutine ( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp ) /*++ Routine Description: Arguments: none. Return Value: --*/ { PCNhSock Socketp = NULL; PICQ_PEER IcqPeerp = NULL; ULONG Error; // ASSERT(Bufferp); Socketp = Bufferp->Socketp; IcqPeerp = reinterpret_cast(Bufferp->Context); // IcqClientp = reinterpret_cast(Bufferp->Context2); ICQ_TRC(TM_IO, TL_TRACE, ("> IcqPeerConnectionCompletionRoutine")); // ASSERT on all of them. do { if(ErrorCode) { // Do - we need it? // Delete the Shadow mapping // // if can't connect then Delete the existing Socket to which we have // established connection. // if(IcqPeerp->MappingDirection is IcqFlagOutgoing) { STOP_COMPONENT(IcqPeerp->ToClientSocketp); //DEREFERENCE_COMPONENT(IcqPeerp->ToClientSocketp); } else // incoming { STOP_COMPONENT(IcqPeerp->ToPeerSocketp); //DEREFERENCE_COMPONENT(IcqPeerp->ToClientSocketp); } break; } else { ULONG srcIp; USHORT srcPort; Socketp->NhQueryRemoteEndpointSocket(&srcIp, &srcPort); // // ICQ_TRC(TM_IO, TL_TRACE, ("Connected to - Remote end is at %s:%hu", INET_NTOA(srcIp), htons(srcPort))); // // Activate The Connection // Issue the Read Operations on both Sockets with the Peer as their // Context // if(IcqPeerp->MappingDirection is IcqFlagOutgoing) { IcqPeerp->ToPeerSocketp = Socketp; ICQ_TRC(TM_MSG, TL_DUMP, ("Mapping is outGoing.. this socket is to the peer")); } else { IcqPeerp->ToClientSocketp = Socketp; } ICQ_TRC(TM_IO, TL_TRACE, ("Issuing firstRead")); Socketp = IcqPeerp->ToClientSocketp; REF_COMPONENT( IcqPeerp, eRefIoRead ); Error = Socketp->NhReadStreamSocket ( g_IcqComponentReferencep, NULL, ICQ_BUFFER_SIZE, // we should give a size 0, IcqPeerReadCompletionRoutine, IcqPeerp, NULL ); if(Error) { ErrorOut(); ICQ_TRC(TM_MSG, TL_ERROR, (" ERROR - Read failed on ToClient Sock")); DEREF_COMPONENT( IcqPeerp, eRefIoRead ); break; } // // The other read operation // ICQ_TRC(TM_IO, TL_TRACE, ("Issuing second Read")); Socketp = IcqPeerp->ToPeerSocketp; REF_COMPONENT( IcqPeerp, eRefIoRead ); Error = Socketp->NhReadStreamSocket ( g_IcqComponentReferencep, NULL, ICQ_BUFFER_SIZE, 0, IcqPeerReadCompletionRoutine, IcqPeerp, NULL ); if(Error) { ErrorOut(); ICQ_TRC(TM_MSG, TL_ERROR, (" ERROR - Read failed on ToPeer Sock")); STOP_COMPONENT(IcqPeerp->ToClientSocketp); // reference will be cleared later DEREF_COMPONENT( IcqPeerp, eRefIoRead); DEREF_COMPONENT( IcqPeerp, eRefIoRead ); break; } // // Reference the ICQ_PEER twice due to two read issues IcqPeerp->bActivated = TRUE; } } while (FALSE); DEREF_COMPONENT( Bufferp->Socketp, eRefIoConnect ); DEREF_COMPONENT( IcqPeerp, eRefIoConnect); DEREF_COMPONENT( g_IcqComponentReferencep, eRefIoConnect ); } VOID IcqPeerReadCompletionRoutine ( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp ) /*++ Routine Description: Reads TCP data between the peers. Within these flows there will be a place where the Data channel is negotiated. Arguments: none. Return Value: --*/ { PICQ_PEER IcqPeerp = NULL; PCNhSock Socketp = NULL; PCNhSock OtherSocketp = NULL; ULONG Error = NO_ERROR; // ASSeRT(Bufferp); Socketp = Bufferp->Socketp; IcqPeerp = reinterpret_cast(Bufferp->Context); ICQ_TRC(TM_IO, TL_TRACE, ("> IcqPeerReadCompletionRoutine E:(%X) D:(%u)", ErrorCode, BytesTransferred)); do { if( (ErrorCode != 0) || ((ErrorCode== 0) && (BytesTransferred == 0)) ) { ICQ_TRC(TM_IO, TL_ERROR, ("Stoppping the Peer SESSION")); IcqPeerp->EndPeerSessionForClient(Socketp); break; } else { if(BytesTransferred) { OtherSocketp = IcqPeerp->ToClientSocketp; ICQ_TRC(TM_IO, TL_TRACE, (" Regular Data from a Peer(%u)/Client(%s) Socket", IcqPeerp->PeerUIN, // Peer-UIN INET_NTOA(IcqPeerp->iKey1))); // Client-IP // // Determine which direction this Socket is from.. // if(OtherSocketp is Socketp) { // // NOTE: if it is from the ToClientSocketp then Process it // IcqPeerp->ProcessOutgoingPeerMessage(Bufferp->Buffer, Bufferp->BytesTransferred); OtherSocketp = IcqPeerp->ToPeerSocketp; } // then forward it to the other side by simply writing it . Error = OtherSocketp->NhWriteStreamSocket(g_IcqComponentReferencep, Bufferp, BytesTransferred, 0, IcqWriteCompletionRoutine, NULL, NULL); if(Error) { ICQ_TRC(TM_MSG, TL_ERROR, ("Error - In writing to the other side")); } } // // Issue another Read operation // REF_COMPONENT( IcqPeerp, eRefIoRead ); Error = Socketp->NhReadStreamSocket(g_IcqComponentReferencep, NULL, ICQ_BUFFER_SIZE, 0, IcqPeerReadCompletionRoutine, IcqPeerp, NULL); if(Error) { DEREF_COMPONENT( IcqPeerp, eRefIoRead); ICQ_TRC(TM_MSG, TL_ERROR, ("Peer connection no more??")); } } } while (FALSE); DEREF_COMPONENT( Socketp, eRefIoRead ); DEREF_COMPONENT( IcqPeerp, eRefIoRead ); DEREF_COMPONENT( g_IcqComponentReferencep, eRefIoRead ); } // End of *IcqPeerReadCompletionRoutine*