Source code of Windows XP (NT5)
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.

1455 lines
31 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. Author:
  6. Savas Guven (savasg) 27-Nov-2000
  7. Revision History:
  8. --*/
  9. #include "stdafx.h"
  10. //
  11. // STATIC MEMBER Initialization
  12. //
  13. const PCHAR _ICQ_CLIENT::ObjectNamep = "ICQ_CLIENT";
  14. const PCHAR _ICQ_PEER::ObjectNamep = "ICQ_PEER";
  15. _ICQ_PEER::_ICQ_PEER()
  16. :ToClientSocketp(NULL),
  17. ToPeerSocketp(NULL),
  18. PeerUIN(0),
  19. PeerVer(0),
  20. PeerIp(0),
  21. PeerPort(0),
  22. bActivated(FALSE),
  23. bShadowMappingExists(FALSE),
  24. MappingDirection(IcqFlagNeutral),
  25. ShadowRedirectp(NULL),
  26. OutgoingPeerControlRedirectp(NULL),
  27. IncomingDataRedirectp(NULL)
  28. {
  29. }
  30. _ICQ_PEER::~_ICQ_PEER()
  31. /*++
  32. Routine Description:
  33. Arguments:
  34. none.
  35. Return Value:
  36. --*/
  37. {
  38. if(this->bCleanupCalled is FALSE)
  39. {
  40. _ICQ_PEER::ComponentCleanUpRoutine();
  41. }
  42. this->bCleanupCalled = FALSE;
  43. }
  44. void
  45. _ICQ_PEER::ComponentCleanUpRoutine()
  46. /*++
  47. Routine Description:
  48. Arguments:
  49. none.
  50. Return Value:
  51. --*/
  52. {
  53. DispatchRequest DReq;
  54. PROFILER(TM_IO, TL_INFO, ("PEER COMPONENT_CLEANING %u", this->PeerUIN));
  55. // Cancel the Shadow Mapping if there is any
  56. if(this->ShadowRedirectp)
  57. {
  58. this->ShadowRedirectp->Cancel();
  59. this->ShadowRedirectp->Release();
  60. this->ShadowRedirectp = NULL;
  61. this->MappingDirection = IcqFlagNeutral;
  62. }
  63. if(this->IncomingDataRedirectp != NULL)
  64. {
  65. this->IncomingDataRedirectp->Cancel();
  66. this->IncomingDataRedirectp->Release();
  67. this->IncomingDataRedirectp = NULL;
  68. }
  69. if(this->OutgoingPeerControlRedirectp)
  70. {
  71. this->OutgoingPeerControlRedirectp->Cancel();
  72. this->OutgoingPeerControlRedirectp->Release();
  73. this->OutgoingPeerControlRedirectp = NULL;
  74. }
  75. //
  76. // NOTE: Delete the Dispatcher entries
  77. //
  78. DReq.dstIp = this->PeerIp;
  79. DReq.dstPort= this->PeerPort;
  80. DReq.srcIp = 0;
  81. DReq.srcPort= 0;
  82. // g_IcqPeerDispatcherp->DeleteDispatchRequest(
  83. //
  84. // Close and Dereference the local sockets if there is any.
  85. //
  86. if ( ToPeerSocketp != NULL )
  87. {
  88. STOP_COMPONENT( ToPeerSocketp );
  89. DEREF_COMPONENT( ToPeerSocketp, eRefInitialization );
  90. ToPeerSocketp = NULL;
  91. }
  92. if ( ToClientSocketp != NULL )
  93. {
  94. STOP_COMPONENT( ToClientSocketp );
  95. DEREF_COMPONENT( ToClientSocketp, eRefInitialization );
  96. ToClientSocketp = NULL;
  97. }
  98. this->bCleanupCalled = TRUE;
  99. }
  100. void
  101. _ICQ_PEER::StopSync(void)
  102. /*++
  103. Routine Description:
  104. Stop the sockets if there are any...
  105. Arguments:
  106. none.
  107. Return Value:
  108. --*/
  109. {
  110. if(this->ToClientSocketp != NULL)
  111. {
  112. STOP_COMPONENT(this->ToClientSocketp);
  113. }
  114. if(this->ToPeerSocketp != NULL)
  115. {
  116. STOP_COMPONENT(this->ToPeerSocketp);
  117. }
  118. this->Deleted = TRUE;
  119. }
  120. ULONG
  121. _ICQ_PEER::EndPeerSessionForClient(PCNhSock ClosedSocketp)
  122. {
  123. PROFILER(TM_MSG, TL_INFO, ("> EndPeerSessionForClient"));
  124. //
  125. // Find the proper Socket and Dereference it.
  126. //
  127. if ( ClosedSocketp is this->ToClientSocketp )
  128. {
  129. DEREF_COMPONENT( this->ToClientSocketp, eRefInitialization );
  130. this->ToClientSocketp = NULL;
  131. if ( this->ToPeerSocketp != NULL )
  132. {
  133. STOP_COMPONENT( this->ToPeerSocketp );
  134. }
  135. }
  136. else if ( ClosedSocketp is this->ToPeerSocketp )
  137. {
  138. DEREF_COMPONENT( this->ToPeerSocketp, eRefInitialization );
  139. this->ToPeerSocketp = NULL;
  140. if( this->ToPeerSocketp != NULL )
  141. {
  142. STOP_COMPONENT( this->ToPeerSocketp );
  143. }
  144. }
  145. else
  146. {
  147. ASSERT(FALSE);
  148. }
  149. //
  150. // The Data Redirects Should be cleaned here.
  151. //
  152. if(this->IncomingDataRedirectp != NULL)
  153. {
  154. this->IncomingDataRedirectp->Cancel();
  155. this->IncomingDataRedirectp->Release();
  156. this->IncomingDataRedirectp = NULL;
  157. }
  158. if(this->ShadowRedirectp)
  159. {
  160. this->ShadowRedirectp->Cancel();
  161. this->ShadowRedirectp->Release();
  162. this->ShadowRedirectp = NULL;
  163. this->bActivated = FALSE;
  164. this->MappingDirection = IcqFlagNeutral;
  165. }
  166. return NO_ERROR;
  167. }
  168. // ************************************************
  169. // ICQ_CLIENT MEMBER FUNCTION
  170. // ************************************************
  171. //
  172. //
  173. //
  174. _ICQ_CLIENT::_ICQ_CLIENT()
  175. :ServerSocketp(NULL),
  176. ShadowRedirectp(NULL),
  177. IncomingPeerControlRedirectionp(NULL),
  178. ClientSocketp(NULL),
  179. ClientIp(0),
  180. ClientToServerPort(0),
  181. ClientToPeerPort(0),
  182. ImitatedPeerPort(0),
  183. UIN(0),
  184. ClientVer(0),
  185. ServerIp(0),
  186. ServerPort(0),
  187. TimerContextp(NULL)
  188. {
  189. }
  190. _ICQ_CLIENT::~_ICQ_CLIENT()
  191. /*++
  192. Routine Description:
  193. Arguments:
  194. none.
  195. Return Value:
  196. --*/
  197. {
  198. if(this->bCleanupCalled is FALSE)
  199. {
  200. _ICQ_CLIENT::ComponentCleanUpRoutine();
  201. }
  202. this->bCleanupCalled = FALSE;
  203. }
  204. void
  205. _ICQ_CLIENT::ComponentCleanUpRoutine(void)
  206. /*++
  207. Routine Description:
  208. Arguments:
  209. none.
  210. Return Value:
  211. --*/
  212. {
  213. ULONG Error = NO_ERROR;
  214. DispatchRequest DReq;
  215. PICQ_PEER IcqPeerp = NULL;
  216. PROFILER(TM_MSG, TL_INFO, ("CLIENT COMPONENT_CLEANING %u", this->UIN));
  217. //
  218. // We need to DELETE the Dispatcher Requests made for the
  219. // Peer, tracerse the List of the Peers and Request the Removal
  220. // of these (OUTGOING PEER SESSION - REDIRECT) deletion.
  221. //
  222. for(IcqPeerp = dynamic_cast<PICQ_PEER> (this->IcqPeerList.SearchNodeKeys(0, 0));
  223. IcqPeerp != NULL;
  224. IcqPeerp = dynamic_cast<PICQ_PEER>(IcqPeerp->Nextp))
  225. {
  226. DReq.dstIp = IcqPeerp->PeerIp;
  227. DReq.dstPort = IcqPeerp->PeerPort;
  228. DReq.srcIp = this->ClientIp;
  229. DReq.srcPort = 0;
  230. //
  231. // A Remove operation STOPs and DEREFs a Node.
  232. //
  233. this->IcqPeerList.RemoveNodeFromList(IcqPeerp);
  234. Error = g_IcqPeerDispatcherp->DeleteDispatchRequest(&DReq);
  235. if(Error)
  236. {
  237. ICQ_TRC(TM_MSG, TL_ERROR,
  238. ("** !!Can't delete Peer Redirection Dispatch Req !! **"));
  239. }
  240. }
  241. //
  242. // Delete the Dispatcher Requests for the Incoming
  243. // Peer Sessions Redirect Request
  244. //
  245. DReq.dstIp = g_MyPublicIp;
  246. DReq.dstPort = this->ImitatedPeerPort;
  247. DReq.srcIp = 0;
  248. DReq.srcPort = 0;
  249. Error = g_IcqPeerDispatcherp->DeleteDispatchRequest(&DReq);
  250. if(Error)
  251. {
  252. ICQ_TRC(TM_MSG, TL_ERROR,
  253. ("** !! Can't delete CLIENT Incoming Dispatch Req !! **"));
  254. }
  255. if ( FAILED( g_IcqPeerDispatcherp->RemoveDispatchee(this) ) )
  256. {
  257. ICQ_TRC(TM_MSG, TL_ERROR, ("** !! Can't remove Dispatchee "));
  258. ASSERT( FALSE);
  259. }
  260. //
  261. // Dereference the the Shared ClientSocketp
  262. if(ClientSocketp != NULL)
  263. {
  264. DEREF_COMPONENT( this->ClientSocketp, eRefInitialization );
  265. this->ClientSocketp = NULL;
  266. }
  267. //
  268. // delete and/or Dereference the ServerSocketp
  269. if(ServerSocketp != NULL)
  270. {
  271. STOP_COMPONENT(ServerSocketp);
  272. DEREF_COMPONENT( this->ServerSocketp, eRefInitialization );
  273. this->ServerSocketp;
  274. }
  275. //
  276. // Clear the Shadow Mappings if therer are any.
  277. //
  278. if(this->ShadowRedirectp != NULL)
  279. {
  280. this->ShadowRedirectp->Cancel();
  281. this->ShadowRedirectp->Release();
  282. this->ShadowRedirectp = NULL;
  283. }
  284. if ( IncomingPeerControlRedirectionp != NULL)
  285. {
  286. IncomingPeerControlRedirectionp->Cancel();
  287. IncomingPeerControlRedirectionp->Release();
  288. IncomingPeerControlRedirectionp = NULL;
  289. this->IncomingRedirectForPeerToClientp = NULL;
  290. }
  291. this->bCleanupCalled = TRUE;
  292. } // _ICQ_CLIENT::ComponentCleanUpRoutine
  293. void
  294. _ICQ_CLIENT::StopSync(void)
  295. /*++
  296. Routine Description:
  297. We have to delete the ASYNC elements in the Peers or within the
  298. current Sockets. The Reads that are issued will have references to
  299. this components which needs to be removed for a complete Garbage
  300. collection. This component has to be declared deleted so that no body
  301. tries to reference it anymore.
  302. It also needs to travers the Peer structures and call the related StopSyncs
  303. approptiately.
  304. Then set this component as deleted.
  305. Arguments:
  306. none.
  307. Return Value:
  308. --*/
  309. {
  310. PICQ_PEER IcqPeerp = NULL;
  311. ICQ_TRC(TM_MSG, TL_TRACE,
  312. ("%s> Stopping the COMPONENT", this->GetObjectName()));
  313. //
  314. // Stop the ServerSocketp
  315. STOP_COMPONENT(this->ServerSocketp);
  316. //
  317. // for each peer Element Call the STOP_COMPONENT.
  318. // It is important that the Peer Elements are not deleted here.
  319. //
  320. for(IcqPeerp = dynamic_cast<PICQ_PEER>(this->IcqPeerList.SearchNodeKeys(0,0));
  321. IcqPeerp != NULL;
  322. IcqPeerp = dynamic_cast<PICQ_PEER>(this->IcqPeerList.SearchNodeKeys(0,0))
  323. )
  324. {
  325. STOP_COMPONENT(IcqPeerp);
  326. }
  327. this->Deleted = TRUE;
  328. } // _ICQ_CLIENT::StopSync
  329. ULONG
  330. _ICQ_CLIENT::DispatchCompletionRoutine(PDispatchReply DispatchReplyp)
  331. /*++
  332. Routine Description:
  333. Arguments:
  334. none.
  335. Return Value:
  336. --*/
  337. {
  338. PICQ_PEER IcqPeerp = NULL;
  339. PCNhSock * cupHolder = NULL;
  340. ULONG Error = NO_ERROR;
  341. // if(DispatchReplyp is NULL) return 0; ASSERT on it?
  342. ICQ_TRC(TM_MSG, TL_TRACE, (" Dispatch Completion Routine of ICQcl "));
  343. //
  344. // Find the Appropriate Peer entry which has caused this completion routine
  345. // Note that all the peer entries have the UIN as the search Key.
  346. // thus if this Reply has the IcqFlagOutgoing as the flag we should just
  347. // Look at this list to see which or where we're sending..
  348. // Otherwise we should look at the src addresses and either way we have to
  349. // scan the whole List to find the appropriate entry.
  350. //
  351. for(IcqPeerp = dynamic_cast<PICQ_PEER> (this->IcqPeerList.SearchNodeKeys(0, 0));
  352. IcqPeerp != NULL;
  353. IcqPeerp = dynamic_cast<PICQ_PEER>(IcqPeerp->Nextp))
  354. {
  355. if(DispatchReplyp->dispatch.DirectionContext is IcqFlagOutgoing)
  356. {
  357. if(IcqPeerp->PeerIp is DispatchReplyp->dispatch.dstIp &&
  358. IcqPeerp->PeerPort is DispatchReplyp->dispatch.dstPort)
  359. {
  360. ICQ_TRC(TM_MSG, TL_TRACE,
  361. ("connection from inside to UIN %lu", IcqPeerp->PeerUIN));
  362. IcqPeerp->ToClientSocketp = DispatchReplyp->Socketp;
  363. cupHolder = &IcqPeerp->ToClientSocketp ;
  364. IcqPeerp->MappingDirection = IcqFlagOutgoing;
  365. break;
  366. }
  367. }
  368. else // Incoming. BUG BUG: add feature #14 from -The- TEXT
  369. {
  370. //DispatchReplyp->dispatch.srcPort;
  371. if(IcqPeerp->PeerIp is DispatchReplyp->dispatch.srcIp)
  372. {
  373. ICQ_TRC(TM_MSG, TL_TRACE,
  374. ("connection -from- UIN %lu", IcqPeerp->PeerUIN));
  375. IcqPeerp->ToPeerSocketp = DispatchReplyp->Socketp;
  376. cupHolder = &IcqPeerp->ToPeerSocketp ;
  377. DispatchReplyp->dispatch.dstIp = this->ClientIp;
  378. DispatchReplyp->dispatch.dstPort = this->ClientToPeerPort;
  379. IcqPeerp->MappingDirection = IcqFlagIncoming;
  380. break;
  381. }
  382. } // if-else
  383. } // for
  384. if(IcqPeerp is NULL)
  385. {
  386. ICQ_TRC(TM_MSG, TL_ERROR,
  387. ("NO IcqPeer has been found DELETING THE ACCEPTED SOCKET"));
  388. ReportExistingPeers();
  389. DEREF_COMPONENT( DispatchReplyp->Socketp, eRefInitialization );
  390. delete DispatchReplyp;
  391. return 0;
  392. }
  393. if(Error = IcqPeerp->InitiatePeerConnection(DispatchReplyp))
  394. {
  395. ICQ_TRC(TM_MSG, TL_ERROR, ("Error - Initiation Peer connection has failed "));
  396. STOP_COMPONENT(DispatchReplyp->Socketp);
  397. DEREF_COMPONENT( DispatchReplyp->Socketp, eRefInitialization );
  398. *cupHolder = NULL;
  399. }
  400. delete DispatchReplyp;
  401. return Error;
  402. }
  403. ULONG
  404. _ICQ_CLIENT::Initialize(
  405. PNH_BUFFER Bufferp,
  406. ULONG clientIp,
  407. USHORT clientPort,
  408. ULONG serverIp,
  409. USHORT serverPort,
  410. PCNhSock localClientSocketp
  411. )
  412. /*++
  413. Routine Description:
  414. If there are existing set of informations then it should be noted that,
  415. We need to make a consistency check or pass on them.
  416. A new client ~ server session may effect the ongoing TCP streams.. Thus
  417. the decisions should be made wisely as it would mean of scavenging a lot
  418. of resources and cycles.
  419. - Initialy we don't have any data so, we store them.
  420. - Here we get the local TCP port information and need to create mappings
  421. for them. (defered)
  422. Arguments:
  423. none.
  424. Return Value:
  425. --*/
  426. {
  427. ULONG hr = S_OK;
  428. ASSERT(Bufferp != NULL);
  429. ASSERT(localClientSocketp != NULL);
  430. do
  431. {
  432. if(this->ClientIp != 0)
  433. {
  434. ICQ_TRC(TM_MSG, TL_ERROR,
  435. ("** !! ERROR - RE-INITING of client %s",
  436. INET_NTOA(ClientIp)));
  437. ASSERT( FALSE );
  438. }
  439. else // first time init
  440. {
  441. ULONG InterfaceIp;
  442. this->ClientIp = clientIp;
  443. this->ClientToServerPort = clientPort;
  444. this->ServerIp = serverIp;
  445. this->ServerPort = serverPort;
  446. //
  447. // Since we're sharing the socket back to the client
  448. // it should be properly referenced so that it is not deleted randomly
  449. //
  450. ClientSocketp = localClientSocketp;
  451. REF_COMPONENT( localClientSocketp, eRefIoSharing );
  452. //
  453. // Create a new UDP socket;
  454. //
  455. NEW_OBJECT( ServerSocketp, CNhSock );
  456. if( ServerSocketp is NULL )
  457. {
  458. ICQ_TRC(TM_MSG, TL_ERROR, ("** !! Socket Creation hr"));
  459. hr = E_OUTOFMEMORY;
  460. break;
  461. }
  462. InterfaceIp = InterfaceForDestination(ServerIp);
  463. ICQ_TRC(TM_MSG, TL_TRACE,
  464. ("The InterfaceIP for the PRoxy ~ Server is %s",
  465. INET_NTOA(InterfaceIp)));
  466. hr = ServerSocketp->NhCreateDatagramSocket(InterfaceIp,
  467. 0,
  468. NULL);
  469. if ( hr )
  470. {
  471. ICQ_TRC(TM_MSG, TL_ERROR, ("CLI !!> Socket Creation hr"));
  472. hr = HRESULT_FROM_WIN32( hr );
  473. break;
  474. }
  475. PICQ_CLIENT tempClientp = this;
  476. REF_COMPONENT( tempClientp, eRefIoRead );
  477. // issue a Read operation on the Server Socket here.
  478. hr = ServerSocketp->NhReadDatagramSocket(g_IcqComponentReferencep,
  479. NULL,
  480. ReadServerCompletionRoutine,
  481. this,
  482. NULL);
  483. if ( hr )
  484. {
  485. ICQ_TRC(TM_MSG, TL_ERROR, ("Read hr "));
  486. DEREF_COMPONENT( tempClientp, eRefIoRead );
  487. hr = HRESULT_FROM_WIN32( hr );
  488. break;
  489. }
  490. //
  491. // Initialize Once.
  492. //
  493. hr = g_IcqPeerDispatcherp->InitDispatchee(this);
  494. if ( hr )
  495. {
  496. ASSERT( FALSE ); // handle this case later
  497. }
  498. //
  499. // Now we can pass the Buffer and the destination address to
  500. // the generic ServerRead
  501. //
  502. hr = this->ClientRead(Bufferp, serverIp, serverPort);
  503. if(hr)
  504. {
  505. ASSERT(FALSE);
  506. }
  507. }
  508. } while ( FALSE );
  509. if ( FAILED(hr) )
  510. {
  511. }
  512. //
  513. // The Search Key for this
  514. //
  515. this->iKey1 = clientIp;
  516. this->iKey2 = 0;
  517. return hr;
  518. }
  519. //
  520. //
  521. //
  522. ULONG
  523. _ICQ_CLIENT::ServerRead(
  524. PNH_BUFFER Bufferp,
  525. ULONG serverIp,
  526. USHORT serverPort
  527. )
  528. /*++
  529. Routine Description:
  530. Arguments:
  531. none.
  532. Return Value:
  533. --*/
  534. {
  535. ULONG Error = NO_ERROR;
  536. if(Bufferp is NULL)
  537. {
  538. return E_INVALIDARG;
  539. }
  540. ICQ_TRC(TM_MSG, TL_DUMP,
  541. ("UDP - Server is Sending TO Client %s", INET_NTOA(ClientIp)));
  542. Error = IcqServerToClientUdp(Bufferp->Buffer,
  543. Bufferp->BytesTransferred);
  544. //
  545. // Write to Destination of the Processed packet
  546. //
  547. Error = ClientSocketp->NhWriteDatagramSocket(g_IcqComponentReferencep,
  548. this->ClientIp,
  549. this->ClientToServerPort,
  550. Bufferp,
  551. Bufferp->BytesTransferred,
  552. IcqWriteCompletionRoutine,
  553. NULL,
  554. NULL);
  555. if(Error)
  556. {
  557. ICQ_TRC(TM_MSG, TL_ERROR,
  558. ("** !! SRead> problem at writing to client %s",
  559. INET_NTOA(this->ClientIp)));
  560. NhReleaseBuffer(Bufferp);
  561. ErrorOut();
  562. }
  563. return Error;
  564. }
  565. //
  566. //
  567. //
  568. ULONG
  569. _ICQ_CLIENT::ClientRead(
  570. PNH_BUFFER Bufferp,
  571. ULONG serverIp,
  572. USHORT serverPort
  573. )
  574. /*++
  575. Routine Description:
  576. Reads the data coming from a client, going to the server
  577. We're checking this UDP packet so that:
  578. * the client Address, and port numbers so that they are valid and up-to-date
  579. * the server address/port is also checked for verification
  580. * the packets are sent to processing function
  581. * and then UDP packets are forwarded to Server
  582. Arguments:
  583. none.
  584. Return Value:
  585. --*/
  586. {
  587. ULONG srcIp, dstIp = this->ServerIp, Error;
  588. USHORT srcPort, dstPort = this->ServerPort;
  589. ULONG LocalIp = 0;
  590. USHORT LocalPort = 0;
  591. //
  592. // Decide = Where is the data coming from or ASSERT(Bufferp);
  593. //
  594. ASSERT(Bufferp != NULL);
  595. //
  596. // Outgoing packet reset the Timeout for this.
  597. //
  598. this->ResetTimer();
  599. srcIp = Bufferp->ReadAddress.sin_addr.S_un.S_addr;
  600. srcPort = Bufferp->ReadAddress.sin_port;
  601. ICQ_TRC(TM_MSG, TL_DUMP, ("ICQ_CL->ClientRead> Sending TO Server %s",
  602. INET_NTOA(serverIp)));
  603. ASSERT(srcIp is ClientIp);
  604. //
  605. // ClientPort has changed.
  606. //
  607. if(srcPort != ClientToServerPort)
  608. {
  609. ICQ_TRC(TM_MSG, TL_INFO,
  610. ("CLIENT PORT HAS CHANGED !!!!!! new %hu: old %hu ",
  611. htons(srcPort), htons(ClientToServerPort)));
  612. ClientToServerPort = srcPort;
  613. }
  614. //
  615. // Decide wether shadow mapping is necessary or not.
  616. // if the destination is changed than we need another shadow mapping - delete the old one.
  617. //
  618. //
  619. // decide the Destination Address
  620. // if we have an existing mapping and the address has changed than
  621. // delete the OLD SHADOW mapping.. and re-init a new one.
  622. //
  623. if( (this->ServerIp != serverIp) ||
  624. (this->ServerPort != serverPort) )
  625. {
  626. ICQ_TRC(TM_MSG, TL_ERROR,
  627. ("!! A NEW SERVER IS SELECTED !! %s ", INET_NTOA(serverIp)));
  628. //
  629. // DELETE the existing shadow mapping if there is one.
  630. //
  631. if(this->ShadowRedirectp != NULL)
  632. {
  633. ICQ_TRC(TM_MSG, TL_TRACE,
  634. ("Cancelling the Shadow Redirect i.e. CreateProxyConnect"));
  635. Error = ShadowRedirectp->Cancel();
  636. if( FAILED(Error) )
  637. {
  638. ICQ_TRC(TM_MSG, TL_ERROR,
  639. ("** !! - Problemo with Cancelling ShadowRedirect- !! **"));
  640. }
  641. ShadowRedirectp->Release();
  642. this->ShadowRedirectp = NULL;
  643. }
  644. //
  645. // store the new informaiton
  646. //
  647. this->ServerIp = serverIp;
  648. this->ServerPort = serverPort;
  649. }
  650. dstIp = this->ServerIp;
  651. dstPort = this->ServerPort;
  652. //
  653. // NOTE: Check for the Error value here..
  654. // Process the Message
  655. //
  656. Error = IcqClientToServerUdp(Bufferp->Buffer,
  657. Bufferp->BytesTransferred);
  658. if(Error)
  659. {
  660. ICQ_TRC(TM_MSG, TL_ERROR,
  661. ("Can't Allocate enough resource for Login Packet"));
  662. NhReleaseBuffer(Bufferp);
  663. return Error;
  664. }
  665. //
  666. // Check the shadow-mapping to the destination from this port.
  667. // This should have been created in the Initialization phase.
  668. //
  669. if ( this->ShadowRedirectp is NULL )
  670. {
  671. ICQ_TRC(TM_MSG, TL_TRACE, ("!! CREATING SHADOW redirect - !!"));
  672. //
  673. // Get the local endpoint?! for src address
  674. //
  675. ServerSocketp->NhQueryLocalEndpointSocket(&LocalIp,
  676. &LocalPort);
  677. Error = g_IAlgServicesp->GetBestSourceAddressForDestinationAddress(dstIp,
  678. TRUE,
  679. &LocalIp);
  680. if( FAILED(Error) )
  681. {
  682. ICQ_TRC(TM_MSG, TL_ERROR,
  683. ("** !! - Best Source Address for Dest Failed !! **"));
  684. ASSERT ( FALSE );
  685. }
  686. ICQ_TRC(TM_MSG, TL_TRACE, ("Best Source address is decided as %s", INET_NTOA(LocalIp)));
  687. Error = g_IAlgServicesp->PrepareProxyConnection(eALG_UDP,
  688. LocalIp,
  689. LocalPort,
  690. dstIp,
  691. dstPort,
  692. TRUE,
  693. &ShadowRedirectp);
  694. //
  695. // If the Shadow Redirect fails don't go further.
  696. // Release the Buffer and exit,
  697. // this may be a transitory behaviour.
  698. //
  699. if( FAILED(Error) )
  700. {
  701. ICQ_TRC(TM_MSG, TL_ERROR,
  702. (" ** !! - ShadowRedirect has Failed - proxy connection !! **"));
  703. NhReleaseBuffer(Bufferp);
  704. this->ShadowRedirectp = NULL;
  705. return E_FAIL;
  706. }
  707. }
  708. //
  709. // Write to Destination of the Processed packet
  710. //
  711. Error = ServerSocketp->NhWriteDatagramSocket(g_IcqComponentReferencep,
  712. dstIp,
  713. dstPort,
  714. Bufferp,
  715. Bufferp->BytesTransferred,
  716. IcqWriteCompletionRoutine,
  717. NULL,
  718. NULL);
  719. if(Error)
  720. {
  721. ICQ_TRC(TM_MSG, TL_ERROR, ("** !! WRITE ERROR !!! **"));
  722. NhReleaseBuffer(Bufferp);
  723. }
  724. return Error;
  725. }
  726. //
  727. //
  728. //
  729. ISecondaryControlChannel *
  730. _ICQ_CLIENT::PeerRedirection(
  731. ULONG dstIp,
  732. USHORT dstPort,
  733. ULONG srcIp OPTIONAL,
  734. USHORT srcPort OPTIONAL,
  735. ICQ_DIRECTION_FLAGS DirectionContext
  736. )
  737. /*++
  738. Routine Description:
  739. The Advertised PEER-CONTROL connection port is the dstPort here. This
  740. function creates the Redirection for this connection as a
  741. SecondaryControl Channel connection.
  742. Then indicates that a incoming TCP connection is going to be dispatched
  743. by the Dispatcher Class to us. So it request a Dispatch Service.
  744. Arguments:
  745. none.
  746. Return Value:
  747. --*/
  748. {
  749. ULONG Error = NO_ERROR;
  750. ISecondaryControlChannel* SecondaryControlRedirectionp = NULL;
  751. PDispatchRequest DRp = NULL;
  752. ULONG PrivateAddr = 0, PublicAddr = 0, RemoteAddr = 0, ListenAddr = 0;
  753. USHORT PrivatePort = 0, PublicPort = 0, RemotePort = 0, ListenPort = 0;
  754. do
  755. {
  756. //
  757. // step 2 - create a redirection for the TCP packets destined to this port
  758. // NOTE: should we change this to a FULL redirect one?
  759. //
  760. g_IcqPeerDispatcherp->GetDispatchInfo( &ListenAddr, &ListenPort );
  761. ICQ_TRC(TM_MSG, TL_DUMP, ("Listen addr of Dispatcher %s(%hu)",
  762. INET_NTOA(ListenAddr), ListenPort));
  763. ASSERT ( ListenAddr != 0 );
  764. ASSERT ( ListenPort != 0 );
  765. if ( DirectionContext is eALG_INBOUND )
  766. {
  767. PrivateAddr = 0;
  768. PrivatePort = 0;
  769. PublicAddr = dstIp;
  770. PublicPort = dstPort;
  771. RemoteAddr = 0;
  772. RemotePort = 0;
  773. ICQ_TRC(TM_MSG, TL_INFO,
  774. ("CLIENT_CONTROL_CHANNEL> Inbound %s:%hu -> Local:%hu",
  775. INET_NTOA(dstIp), htons(dstPort), htons(ListenPort)));
  776. }
  777. else if ( DirectionContext is eALG_OUTBOUND )
  778. {
  779. PrivateAddr = srcIp;
  780. PrivatePort = srcPort;
  781. PublicAddr = 0;
  782. PublicPort = 0;
  783. RemoteAddr = dstIp;
  784. RemotePort = dstPort;
  785. ICQ_TRC(TM_MSG, TL_INFO,
  786. ("CLIENT_CONTROL_CHANNEL> Outbound %s:%hu <- Local:%hu",
  787. INET_NTOA(dstIp), htons(dstPort), htons(ListenPort)));
  788. ICQ_TRC(TM_MSG, TL_INFO,
  789. ("PEER_CONTROL_CHANNEL> Restrict SRC to %s:%u",
  790. INET_NTOA(PrivateAddr), htons(PrivatePort)));
  791. }
  792. else { ASSERT(FALSE); }
  793. Error =
  794. g_IAlgServicesp->CreateSecondaryControlChannel(eALG_TCP,
  795. PrivateAddr,
  796. PrivatePort,
  797. PublicAddr,
  798. PublicPort,
  799. RemoteAddr,
  800. RemotePort,
  801. ListenAddr,
  802. ListenPort,
  803. (ALG_DIRECTION)DirectionContext,
  804. FALSE,
  805. &SecondaryControlRedirectionp);
  806. if( FAILED(Error) || (SecondaryControlRedirectionp is NULL) )
  807. {
  808. ICQ_TRC(TM_MSG, TL_ERROR, ("Can't create the secondary ctrl redirect"));
  809. ASSERT(FALSE);
  810. break;
  811. }
  812. //
  813. // step 3 - Request a Dispatch for this TCP redirection
  814. //
  815. NEW_OBJECT( DRp, DispatchRequest );
  816. if ( DRp is NULL )
  817. {
  818. Error = E_OUTOFMEMORY;
  819. //
  820. // clear redirect
  821. //
  822. SecondaryControlRedirectionp->Cancel();
  823. SecondaryControlRedirectionp->Release();
  824. SecondaryControlRedirectionp = NULL;
  825. ICQ_TRC(TM_MSG, TL_ERROR,
  826. ("Error - Out of memory to create a new DispatchRequest"));
  827. break;
  828. }
  829. DRp->dstIp = dstIp; // *
  830. DRp->dstPort = dstPort; //*
  831. DRp->srcIp = srcIp;
  832. DRp->srcPort = srcPort;
  833. DRp->DirectionContext = DirectionContext;
  834. //
  835. // set the search Keys.
  836. //
  837. DRp->iKey1 = dstIp;
  838. DRp->iKey2 = dstPort;
  839. g_IcqPeerDispatcherp->AddDispatchRequest ( this, DRp );
  840. //
  841. // Store the redirect, to be used in Searches.
  842. //
  843. if ( DirectionContext is eALG_INBOUND )
  844. {
  845. this->IncomingRedirectForPeerToClientp = SecondaryControlRedirectionp;
  846. }
  847. //
  848. // Relinquish the ownwership of the request
  849. //
  850. DEREF_COMPONENT( DRp, eRefInitialization );
  851. } while (FALSE);
  852. return SecondaryControlRedirectionp;
  853. } // _ICQ_CLIENT::PeerRedirection
  854. // scan the list to get the peers
  855. //CLIST g_IcqClientList;
  856. PICQ_CLIENT
  857. ScanTheListForLocalPeer
  858. (
  859. PULONG PeerIp,
  860. PUSHORT PeerPort,
  861. ULONG IcqUIN
  862. )
  863. /*++
  864. Routine Description:
  865. Arguments:
  866. none.
  867. Return Value:
  868. --*/
  869. {
  870. PICQ_CLIENT IcqClientp = NULL;
  871. for(IcqClientp = dynamic_cast<PICQ_CLIENT>(g_IcqClientList.SearchNodeKeys(0, 0));
  872. IcqClientp != NULL;
  873. IcqClientp = dynamic_cast<PICQ_CLIENT>(IcqClientp->Nextp)
  874. )
  875. {
  876. //
  877. // IF we have a hit return TRUE otherwise don't change anything
  878. //
  879. if(IcqClientp->UIN is IcqUIN)
  880. {
  881. if(PeerIp != NULL)
  882. {
  883. if(IcqClientp->ClientIp is g_MyPublicIp)
  884. {
  885. *PeerIp = g_MyPrivateIp;
  886. }
  887. else
  888. {
  889. *PeerIp = IcqClientp->ClientIp;
  890. }
  891. }
  892. if(PeerPort != NULL)
  893. {
  894. *PeerPort = IcqClientp->ClientToPeerPort;
  895. }
  896. return IcqClientp;
  897. }
  898. }
  899. return NULL;
  900. }
  901. //
  902. // Debugging utilities.
  903. //
  904. VOID
  905. _ICQ_CLIENT::ReportExistingPeers(VOID)
  906. /*++
  907. Routine Description:
  908. Report Informations about the All the Peers existing for this client.
  909. Arguments:
  910. none.
  911. Return Value:
  912. none.
  913. --*/
  914. {
  915. PICQ_PEER IcqPeerp = NULL;
  916. for(IcqPeerp = dynamic_cast<PICQ_PEER> (this->IcqPeerList.SearchNodeKeys(0, 0));
  917. IcqPeerp != NULL;
  918. IcqPeerp = dynamic_cast<PICQ_PEER>(IcqPeerp->Nextp))
  919. {
  920. ICQ_TRC(TM_MSG, TL_INFO,
  921. ("PeerIP(PORT) is %s(%hu)",
  922. INET_NTOA(IcqPeerp->PeerIp), htons(IcqPeerp->PeerPort)));
  923. ICQ_TRC(TM_MSG, TL_TRACE,
  924. ("IncomingDataRedirect %s, OutgoingRedirect %s, MappingDirection %s, "\
  925. "ShadowRedirect %s, ToClientSocketp %s, ToPeerSocketp %s",
  926. (IcqPeerp->IncomingDataRedirectp is NULL)?"FALSE":"TRUE",
  927. (IcqPeerp->OutgoingPeerControlRedirectp is NULL)?"FALSE":"TRUE",
  928. (IcqPeerp->MappingDirection is eALG_OUTBOUND)?"OUT":"IN",
  929. (IcqPeerp->ShadowRedirectp is NULL)?"FALSE":"TRUE",
  930. (IcqPeerp->ToClientSocketp is NULL)?"FALSE":"TRUE",
  931. (IcqPeerp->ToPeerSocketp is NULL)?"FALSE":"TRUE"));
  932. }
  933. }
  934. ULONG
  935. _ICQ_CLIENT::DeleteTimer(TIMER_DELETION bHow)
  936. {
  937. if(this->TimerContextp != NULL)
  938. {
  939. if(bHow is eTIMER_DELETION_SYNC)
  940. {
  941. DeleteTimerQueueTimer(g_TimerQueueHandle,
  942. this->TimerContextp->TimerHandle,
  943. INVALID_HANDLE_VALUE);
  944. }
  945. else if(bHow is eTIMER_DELETION_ASYNC)
  946. {
  947. DeleteTimerQueueTimer(g_TimerQueueHandle,
  948. this->TimerContextp->TimerHandle,
  949. NULL);
  950. }
  951. NH_FREE(this->TimerContextp);
  952. this->TimerContextp = NULL;
  953. }
  954. return NO_ERROR;
  955. }
  956. ULONG
  957. _ICQ_CLIENT::ResetTimer(VOID)
  958. {
  959. this->DeleteTimer(eTIMER_DELETION_SYNC);
  960. this->TimerContextp = AllocateAndSetTimer(this->UIN,
  961. ICQ_CLIENT_TIMEOUT,
  962. IcqClientTimeoutHandler);
  963. if(TimerContextp != NULL)
  964. {
  965. return S_OK;
  966. }
  967. return E_FAIL;
  968. }
  969. // typedef VOID (NTAPI * WAITORTIMERCALLBACKFUNC) (PVOID, BOOLEAN ); // winnt
  970. VOID NTAPI IcqClientTimeoutHandler(
  971. PVOID Parameterp,
  972. BOOLEAN TimerOrWaitFired
  973. )
  974. {
  975. PTIMER_CONTEXT TimerContextp = (PTIMER_CONTEXT)Parameterp;
  976. PICQ_CLIENT IcqClientp = NULL;
  977. if(TimerContextp is NULL)
  978. {
  979. return;
  980. }
  981. PROFILER(TM_TIMER, TL_INFO, ("TIME-OUT for Client (%u)",
  982. TimerContextp->uContext));
  983. IcqClientp = ScanTheListForLocalPeer(NULL,
  984. NULL,
  985. TimerContextp->uContext);
  986. //
  987. // Delete the Client Here
  988. //
  989. if(IcqClientp != NULL)
  990. {
  991. IcqClientp->DeleteTimer(eTIMER_DELETION_ASYNC);
  992. g_IcqClientList.RemoveNodeFromList(IcqClientp); // stops and derefs
  993. }
  994. else
  995. {
  996. ASSERT(FALSE);
  997. }
  998. }