Counter Strike : Global Offensive Source Code
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.

732 lines
21 KiB

  1. //===== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "mm_framework.h"
  7. // memdbgon must be the last include file in a .cpp file!!!
  8. #include "tier0/memdbgon.h"
  9. #ifdef _X360
  10. #include "tier0/memdbgoff.h"
  11. #include "fmtstr.h"
  12. #include "protocol.h"
  13. #include "proto_oob.h"
  14. #include "netmessages.h"
  15. #ifndef NETMSG_TYPE_BITS
  16. #define NETMSG_TYPE_BITS 6
  17. #endif
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. ConVar mm_net_channel_timeout( "mm_net_channel_timeout", "100", FCVAR_DEVELOPMENTONLY );
  21. //
  22. // Network manager for Xbox 360 network layer
  23. //
  24. CX360NetworkMgr::CX360NetworkMgr( IX360NetworkEvents *pListener, INetSupport::NetworkSocket_t eSocket ) :
  25. m_pListener( pListener ),
  26. m_eSocket( eSocket ),
  27. m_arrConnections( DefLessFunc( XUID ) ),
  28. m_eState( STATE_IDLE ),
  29. m_eUpdateResult( UPDATE_SUCCESS )
  30. {
  31. }
  32. void CX360NetworkMgr::SetListener( IX360NetworkEvents *pListener )
  33. {
  34. if ( m_eState == STATE_UPDATING )
  35. {
  36. DevMsg( "CX360NetworkMgr::SetListener during network update...\n" );
  37. if ( m_eUpdateResult == UPDATE_SUCCESS )
  38. m_eUpdateResult = UPDATE_LISTENER_CHANGED;
  39. }
  40. // We allow to set listener, we will just return the change
  41. // from inside the update loop
  42. m_pListener = pListener;
  43. }
  44. bool CX360NetworkMgr::IsUpdating() const
  45. {
  46. return m_eState != STATE_IDLE;
  47. }
  48. CX360NetworkMgr::UpdateResult_t CX360NetworkMgr::Update()
  49. {
  50. if ( !m_pListener )
  51. return UPDATE_SUCCESS;
  52. Assert( m_eState == STATE_IDLE );
  53. if ( m_eState != STATE_IDLE )
  54. {
  55. DevWarning( "CX360NetworkMgr::Update when not idle! (state = %d)\n", m_eState );
  56. return UPDATE_SUCCESS;
  57. }
  58. m_eState = STATE_UPDATING;
  59. m_eUpdateResult = UPDATE_SUCCESS;
  60. g_pMatchExtensions->GetINetSupport()->ProcessSocket( m_eSocket, this );
  61. //
  62. // Transmit all our active channels
  63. //
  64. for ( int idx = m_arrConnections.FirstInorder();
  65. idx != m_arrConnections.InvalidIndex(); )
  66. {
  67. XUID xuidKey = m_arrConnections.Key( idx );
  68. ConnectionInfo_t const ci = m_arrConnections.Element( idx ); // get a copy
  69. idx = m_arrConnections.NextInorder( idx );
  70. if ( !xuidKey && m_arrConnections.Count() > 1 )
  71. // skip host designation record if there are other records
  72. // there should be an alias for host too
  73. continue;
  74. // If it is a secure connection in LOST state, then shut it down right away
  75. if ( ci.m_xnaddr.inaOnline.s_addr )
  76. {
  77. if ( g_pMatchExtensions->GetIXOnline()->XNetGetConnectStatus( ci.m_inaddr ) == XNET_CONNECT_STATUS_LOST )
  78. {
  79. DevWarning( "CX360NetworkMgr::Update - Net channel %p is LOST!\n", ci.m_pNetChannel );
  80. ConnectionPeerClose( ci.m_xuid );
  81. // Notify listener
  82. if ( m_pListener )
  83. {
  84. m_pListener->OnX360NetDisconnected( ci.m_xuid );
  85. }
  86. continue;
  87. }
  88. }
  89. if ( ci.m_pNetChannel->IsTimedOut() )
  90. {
  91. DevWarning( "CX360NetworkMgr::Update - Net channel %p is timed out (%.1f s)!\n",
  92. ci.m_pNetChannel, mm_net_channel_timeout.GetFloat() );
  93. ConnectionPeerClose( ci.m_xuid );
  94. // Notify listener
  95. if ( m_pListener )
  96. {
  97. m_pListener->OnX360NetDisconnected( ci.m_xuid );
  98. }
  99. continue;
  100. }
  101. ci.m_pNetChannel->Transmit();
  102. }
  103. bool bSelfDestroy = ( m_eState == STATE_DESTROY_DEFERRED );
  104. m_eState = STATE_IDLE;
  105. if ( bSelfDestroy )
  106. {
  107. Destroy();
  108. return UPDATE_DESTROYED;
  109. }
  110. return m_eUpdateResult;
  111. }
  112. void CX360NetworkMgr::Destroy()
  113. {
  114. // If we are being destroyed in the middle of update loop, then defer the actual destruction
  115. if ( m_eState == STATE_UPDATING )
  116. {
  117. DevMsg( "CX360NetworkMgr::Destroy is deferred...\n" );
  118. m_pListener = NULL;
  119. m_eState = STATE_DESTROY_DEFERRED;
  120. return;
  121. }
  122. Assert( m_eState == STATE_IDLE );
  123. DevMsg( "CX360NetworkMgr::Destroy is deleting this object [%p].\n", this );
  124. // Shutdown all the connections with peers
  125. while ( m_arrConnections.Count() > 0 )
  126. {
  127. ConnectionInfo_t const &ci = m_arrConnections.Element( m_arrConnections.FirstInorder() );
  128. XUID xuidRemote = ci.m_xuid;
  129. ConnectionPeerClose( xuidRemote );
  130. }
  131. delete this;
  132. }
  133. void CX360NetworkMgr::DebugPrint()
  134. {
  135. DevMsg( "CX360NetworkMgr\n" );
  136. DevMsg( " state: %d\n", m_eState );
  137. DevMsg( " connections: %d\n", m_arrConnections.Count() );
  138. for ( int k = m_arrConnections.FirstInorder(), j = 0;
  139. k != m_arrConnections.InvalidIndex();
  140. ++j, k = m_arrConnections.NextInorder( k ) )
  141. {
  142. ConnectionInfo_t const *ci;
  143. ci = &m_arrConnections.Element( k );
  144. DevMsg( " connection%d: %llx [%llx] = channel %p\n", j,
  145. m_arrConnections.Key( k ),
  146. ci->m_xuid, ci->m_pNetChannel );
  147. }
  148. }
  149. //
  150. // Declaration of the X360 network message
  151. //
  152. class CX360NetworkMessageBase : public CNetMessage
  153. {
  154. public:
  155. virtual bool ReadFromBuffer( bf_read &buffer ) { Assert( 0 ); return false; }
  156. virtual bool WriteToBuffer( bf_write &buffer ) const { Assert( 0 ); return false; }
  157. virtual const char *ToString() const { return GetName(); }
  158. virtual int GetType() const { return 20; } // should fit in 5 bits
  159. virtual const char *GetName() const { return "CX360NetworkMessage";}
  160. virtual size_t GetSize() const { return sizeof( *this ); }
  161. };
  162. class CX360NetworkMessageSend : public CX360NetworkMessageBase
  163. {
  164. public:
  165. explicit CX360NetworkMessageSend( KeyValues *pData ) : m_pData( pData ) {}
  166. virtual bool WriteToBuffer( bf_write &buffer ) const;
  167. public:
  168. KeyValues *m_pData;
  169. };
  170. class CX360NetworkMessageRecv : public CX360NetworkMessageBase
  171. {
  172. public:
  173. explicit CX360NetworkMessageRecv( CX360NetworkMgr *pMgr ) : m_pMgr( pMgr ), m_pData( NULL ) {}
  174. ~CX360NetworkMessageRecv();
  175. virtual bool ReadFromBuffer( bf_read &buffer );
  176. virtual bool Process();
  177. public:
  178. CX360NetworkMgr *m_pMgr;
  179. KeyValues *m_pData;
  180. struct GrowStorage_t
  181. {
  182. GrowStorage_t() : m_nBytes( 0 ), m_pbData( NULL ) {}
  183. ~GrowStorage_t() { delete [] m_pbData; m_nBytes = 0; m_pbData = NULL; }
  184. void Grow( int nBytes )
  185. {
  186. if ( m_nBytes < nBytes )
  187. {
  188. delete [] m_pbData;
  189. m_pbData = new unsigned char[ m_nBytes = nBytes ];
  190. }
  191. }
  192. int m_nBytes;
  193. unsigned char *m_pbData;
  194. };
  195. GrowStorage_t m_gsKeyValues;
  196. GrowStorage_t m_gsBinaryData;
  197. };
  198. bool CX360NetworkMessageSend::WriteToBuffer( bf_write &buffer ) const
  199. {
  200. buffer.WriteUBitLong( GetType(), NETMSG_TYPE_BITS );
  201. buffer.WriteLong( g_pMatchExtensions->GetINetSupport()->GetEngineBuildNumber() );
  202. CUtlBuffer bufData;
  203. bufData.ActivateByteSwapping( !CByteswap::IsMachineBigEndian() );
  204. m_pData->WriteAsBinary( bufData );
  205. buffer.WriteLong( bufData.TellMaxPut() );
  206. buffer.WriteBytes( bufData.Base(), bufData.TellMaxPut() );
  207. if ( KeyValues *kvBinary = m_pData->FindKey( "binary" ) )
  208. {
  209. void *pvData = kvBinary->GetPtr( "ptr", NULL );
  210. int nSize = kvBinary->GetInt( "size", 0 );
  211. if ( pvData && nSize )
  212. {
  213. buffer.WriteLong( nSize );
  214. if ( !buffer.WriteBytes( pvData, nSize ) )
  215. return false;
  216. }
  217. else
  218. {
  219. buffer.WriteLong( 0 );
  220. }
  221. }
  222. else
  223. {
  224. buffer.WriteLong( 0 );
  225. }
  226. return !buffer.IsOverflowed();
  227. }
  228. bool CX360NetworkMessageRecv::ReadFromBuffer( bf_read &buffer )
  229. {
  230. if ( buffer.ReadLong() != g_pMatchExtensions->GetINetSupport()->GetEngineBuildNumber() )
  231. return false;
  232. int nDataLen = buffer.ReadLong();
  233. if ( nDataLen <= 0 )
  234. return false;
  235. m_gsKeyValues.Grow( nDataLen );
  236. if ( !buffer.ReadBytes( m_gsKeyValues.m_pbData, nDataLen ) )
  237. return false;
  238. if ( !m_pData )
  239. m_pData = new KeyValues( "" );
  240. else
  241. m_pData->Clear();
  242. CUtlBuffer bufData( m_gsKeyValues.m_pbData, nDataLen, CUtlBuffer::READ_ONLY );
  243. bufData.ActivateByteSwapping( !CByteswap::IsMachineBigEndian() );
  244. if ( !m_pData->ReadAsBinary( bufData ) )
  245. {
  246. m_pData->Clear();
  247. return false;
  248. }
  249. int nBinaryBytes = buffer.ReadLong();
  250. if ( nBinaryBytes > 0 )
  251. {
  252. m_gsBinaryData.Grow( nBinaryBytes );
  253. if ( !buffer.ReadBytes( m_gsBinaryData.m_pbData, nBinaryBytes ) )
  254. return false;
  255. if ( KeyValues *kvPtr = m_pData->FindKey( "binary/ptr" ) )
  256. kvPtr->SetPtr( "", m_gsBinaryData.m_pbData );
  257. }
  258. return !buffer.IsOverflowed();
  259. }
  260. CX360NetworkMessageRecv::~CX360NetworkMessageRecv()
  261. {
  262. if ( m_pData )
  263. m_pData->deleteThis();
  264. m_pData = NULL;
  265. }
  266. bool CX360NetworkMessageRecv::Process()
  267. {
  268. m_pMgr->OnConnectionMessage( m_pData );
  269. return true;
  270. }
  271. void CX360NetworkMgr::ConnectionMessageHandler_t::ConnectionStart( INetChannel *chan )
  272. {
  273. m_pChannel = chan;
  274. CX360NetworkMessageRecv *pMsg = new CX360NetworkMessageRecv( m_pMgr );
  275. m_pChannel->RegisterMessage( pMsg );
  276. }
  277. void CX360NetworkMgr::ConnectionPeerSendMessage( KeyValues *pMsg )
  278. {
  279. DevMsg( 2, "[NET] -> ConnectionPeerSendMessage\n" );
  280. KeyValuesDumpAsDevMsg( pMsg, 1, 2 );
  281. for ( int idx = m_arrConnections.FirstInorder();
  282. idx != m_arrConnections.InvalidIndex();
  283. idx = m_arrConnections.NextInorder( idx ) )
  284. {
  285. XUID xuidKey = m_arrConnections.Key( idx );
  286. ConnectionInfo_t const &ci = m_arrConnections.Element( idx );
  287. if ( !xuidKey && m_arrConnections.Count() > 1 )
  288. // skip host designation record if there are other records
  289. // there should be an alias for host too
  290. continue;
  291. CX360NetworkMessageSend msg( pMsg );
  292. bool bVoice = !Q_stricmp( pMsg->GetName(), "SysSession::Voice" ); // marks the message as voice-channel-VDP-data
  293. ci.m_pNetChannel->SendNetMsg( msg, msg.IsReliable(), bVoice );
  294. ci.m_pNetChannel->Transmit();
  295. DevMsg( 2, " -> %llx (%p : %s)\n", ci.m_xuid, ci.m_pNetChannel,
  296. ci.m_pNetChannel ? ci.m_pNetChannel->GetRemoteAddress().ToString() : "" );
  297. }
  298. }
  299. char const * CX360NetworkMgr::ConnectionPeerGetAddress( XUID xuidRemote )
  300. {
  301. int idxConn = m_arrConnections.Find( xuidRemote );
  302. if ( idxConn == m_arrConnections.InvalidIndex() )
  303. return NULL;
  304. ConnectionInfo_t const &ci = m_arrConnections.Element( idxConn );
  305. if ( !ci.m_pNetChannel )
  306. return NULL;
  307. return ci.m_pNetChannel->GetRemoteAddress().ToString( true );
  308. }
  309. //
  310. // Network communication implementation
  311. //
  312. void CX360NetworkMgr::ConnectionPeerSendConnectionless( XUID xuidRemote, KeyValues *pMsg )
  313. {
  314. // Client should have started an active connection
  315. int idxConn = m_arrConnections.Find( xuidRemote );
  316. if ( idxConn == m_arrConnections.InvalidIndex() )
  317. {
  318. DevWarning( "CX360NetworkMgr::ConnectionPeerSendConnectionless( xuidRemote = %llx ) XUID is not registered!\n",
  319. xuidRemote );
  320. Assert( 0 );
  321. return;
  322. }
  323. DevMsg( 2, "[NET] -> ConnectionPeerSendConnectionless( %llx )\n", xuidRemote );
  324. KeyValuesDumpAsDevMsg( pMsg, 1, 2 );
  325. ConnectionInfo_t const &ci = m_arrConnections.Element( idxConn );
  326. g_pConnectionlessLanMgr->SendPacket( pMsg, ci.m_pNetChannel->GetRemoteAddress().ToString(),
  327. m_eSocket );
  328. }
  329. bool CX360NetworkMgr::ProcessConnectionlessPacket( netpacket_t *packet )
  330. {
  331. Assert( m_pListener );
  332. // Unpack key values
  333. if ( KeyValues *pMsg = g_pConnectionlessLanMgr->UnpackPacket( packet ) )
  334. {
  335. KeyValues::AutoDelete autodelete( pMsg );
  336. DevMsg( 2, "[NET] <- OnX360NetConnectionlessPacket( %s )\n", packet->from.ToString() );
  337. KeyValuesDumpAsDevMsg( pMsg, 1, 2 );
  338. if ( m_pListener && m_pListener->OnX360NetConnectionlessPacket( packet, pMsg ) )
  339. return true;
  340. }
  341. // Otherwise this is an unwanted packet, prevent any more packets from this peer
  342. ConnectionPeerClose( packet );
  343. return false;
  344. }
  345. void CX360NetworkMgr::OnConnectionMessage( KeyValues *pMsg )
  346. {
  347. Assert( m_pListener );
  348. DevMsg( 2, "[NET] <- OnConnectionMessage\n" );
  349. KeyValuesDumpAsDevMsg( pMsg, 1, 2 );
  350. if ( m_pListener )
  351. {
  352. m_pListener->OnX360NetPacket( pMsg );
  353. }
  354. }
  355. void CX360NetworkMgr::OnConnectionClosing( INetChannel *pNetChannel )
  356. {
  357. // This is called in several cases:
  358. // - we called pNetChannel->Shutdown (we wouldn't find this channel then)
  359. // - remote side shut down the channel (we should still find this channel)
  360. // - we crashed while pumping buffered messages (we should still find this channel)
  361. ConnectionInfo_t const *ci = NULL;
  362. for ( int idx = m_arrConnections.FirstInorder();
  363. !ci && idx != m_arrConnections.InvalidIndex();
  364. idx = m_arrConnections.NextInorder( idx ) )
  365. {
  366. ConnectionInfo_t const &record = m_arrConnections.Element( idx );
  367. if ( record.m_pNetChannel == pNetChannel )
  368. ci = &record;
  369. }
  370. if ( !ci )
  371. {
  372. // This is a notification from inside Shutdown initiated by us, ignore
  373. return;
  374. }
  375. // Otherwise something went wrong with the connection and we
  376. // have no other option, but close it and release secure association
  377. XUID xuidRemote = ci->m_xuid;
  378. DevMsg( "CX360NetworkMgr::OnConnectionClosing( xuidRemote = %llx, ip = %s )\n",
  379. xuidRemote, pNetChannel->GetRemoteAddress().ToString( true ) );
  380. ConnectionPeerClose( xuidRemote );
  381. // Notify listener
  382. if ( m_pListener )
  383. {
  384. m_pListener->OnX360NetDisconnected( xuidRemote );
  385. }
  386. }
  387. bool CX360NetworkMgr::ConnectionPeerOpenPassive( XUID xuidRemote, netpacket_t *pktIncoming, XNKID *pxnkidSession /*= NULL*/ )
  388. {
  389. // Check if we already have the corresponding connection open, close it if it is open
  390. if ( m_arrConnections.Find( xuidRemote ) != m_arrConnections.InvalidIndex() )
  391. {
  392. DevWarning( "CX360NetworkMgr::ConnectionPeerOpenPassive( xuidRemote = %llx, ip = %s ) attempted on a duplicate XUID!\n",
  393. xuidRemote, pktIncoming->from.ToString() );
  394. ConnectionPeerClose( xuidRemote );
  395. // Notify listener
  396. if ( m_pListener )
  397. {
  398. m_pListener->OnX360NetDisconnected( xuidRemote );
  399. }
  400. DevWarning( "CX360NetworkMgr::ConnectionPeerOpenPassive proceeding after stale duplicate connection closed...\n" );
  401. }
  402. //
  403. // XNetInAddrToXnAddr
  404. //
  405. XNADDR xnaddrRemote = {0};
  406. XNKID xnkidRemote = {0};
  407. IN_ADDR inaddrRemote = {0};
  408. inaddrRemote.s_addr = pktIncoming->from.GetIPNetworkByteOrder();
  409. if ( pxnkidSession )
  410. xnkidRemote = *pxnkidSession;
  411. if ( pxnkidSession ) // if ( pxnkidSession && !XNetXnKidIsSystemLink( pxnkidSession ) )
  412. {
  413. if ( int err = g_pMatchExtensions->GetIXOnline()->XNetInAddrToXnAddr( inaddrRemote, &xnaddrRemote, &xnkidRemote ) )
  414. {
  415. DevWarning( "CX360NetworkMgr::ConnectionPeerOpenPassive( xuidRemote = %llx, ip = %s ) failed to resolve XNADDR ( code 0x%08X )\n",
  416. xuidRemote, pktIncoming->from.ToString(), err );
  417. return false;
  418. }
  419. }
  420. else
  421. {
  422. xnaddrRemote.ina = inaddrRemote;
  423. xnaddrRemote.wPortOnline = pktIncoming->from.GetPort();
  424. }
  425. if ( pxnkidSession )
  426. *pxnkidSession = xnkidRemote;
  427. //
  428. // Register the connection internally
  429. //
  430. ConnectionMessageHandler_t *pHandler = new ConnectionMessageHandler_t( this, NULL );
  431. INetChannel *pChannel = g_pMatchExtensions->GetINetSupport()->CreateChannel(
  432. m_eSocket, pktIncoming->from,
  433. CFmtStr( "MM:%llx", xuidRemote ), pHandler );
  434. ConnectionInfo_t ci;
  435. ci.m_xuid = xuidRemote;
  436. ci.m_inaddr = inaddrRemote;
  437. ci.m_xnaddr = xnaddrRemote;
  438. ci.m_pNetChannel = pChannel;
  439. ci.m_pHandler = pHandler;
  440. m_arrConnections.Insert( xuidRemote, ci );
  441. DevMsg( "CX360NetworkMgr::ConnectionPeerOpenPassive( xuidRemote = %llx, ip = %s ) succeeded (pNetChannel = %p).\n",
  442. xuidRemote, pktIncoming->from.ToString(), pChannel );
  443. return true;
  444. }
  445. bool CX360NetworkMgr::ConnectionPeerOpenActive( XUID xuidRemote, XSESSION_INFO const &xRemote )
  446. {
  447. // Check if we already have the corresponding connection open
  448. if ( m_arrConnections.Find( xuidRemote ) != m_arrConnections.InvalidIndex() )
  449. {
  450. DevWarning( "CX360NetworkMgr::ConnectionPeerOpenActive( xuidRemote = %llx ) attempted on a duplicate XUID!\n",
  451. xuidRemote );
  452. Assert( 0 );
  453. return false;
  454. }
  455. //
  456. // XNetXnAddrToInAddr
  457. //
  458. XNADDR xnaddrRemote = xRemote.hostAddress;
  459. IN_ADDR inaddrRemote;
  460. if ( 1 ) // if ( !XNetXnKidIsSystemLink( &xRemote.sessionID ) )
  461. {
  462. if ( int err = g_pMatchExtensions->GetIXOnline()->XNetXnAddrToInAddr( &xRemote.hostAddress, &xRemote.sessionID, &inaddrRemote ) )
  463. {
  464. DevWarning( "CX360NetworkMgr::ConnectionPeerOpenActive( xuidRemote = %llx ) failed to resolve XNADDR ( code 0x%08X )\n",
  465. xuidRemote, err );
  466. return false;
  467. }
  468. // Initiate secure connection and key exchange
  469. if ( int err = g_pMatchExtensions->GetIXOnline()->XNetConnect( inaddrRemote ) )
  470. {
  471. DevWarning( "CX360NetworkMgr::ConnectionPeerOpenActive( xuidRemote = %llx ) failed to start key exchange ( code 0x%08X )\n",
  472. xuidRemote, err );
  473. g_pMatchExtensions->GetIXOnline()->XNetUnregisterInAddr( inaddrRemote ); // need to unregister inaddr, otherwise we will leak a secure association
  474. return false;
  475. }
  476. }
  477. else
  478. {
  479. inaddrRemote = xnaddrRemote.ina;
  480. xnaddrRemote.inaOnline.s_addr = 0;
  481. }
  482. //
  483. // Register the connection internally
  484. //
  485. netadr_t inetAddr;
  486. inetAddr.SetType( NA_IP );
  487. inetAddr.SetIPAndPort( inaddrRemote.s_addr, 0 );
  488. ConnectionMessageHandler_t *pHandler = new ConnectionMessageHandler_t( this, NULL );
  489. INetChannel *pChannel = g_pMatchExtensions->GetINetSupport()->CreateChannel(
  490. m_eSocket, inetAddr,
  491. CFmtStr( "MM:XNKID:%llx", ( const uint64 & ) xRemote.sessionID ), pHandler );
  492. ConnectionInfo_t ci;
  493. ci.m_xuid = xuidRemote;
  494. ci.m_inaddr = inaddrRemote;
  495. ci.m_xnaddr = xnaddrRemote;
  496. ci.m_pNetChannel = pChannel;
  497. ci.m_pHandler = pHandler;
  498. m_arrConnections.Insert( xuidRemote, ci );
  499. DevMsg( "CX360NetworkMgr::ConnectionPeerOpenActive( xuidRemote = %llx, xnkid = %llx, ip = %s ) succeeded (pNetChannel = %p), connection %s.\n",
  500. xuidRemote, ( const uint64 & ) xRemote.sessionID, inetAddr.ToString( true ), pChannel,
  501. XNetXnKidIsSystemLink( &xRemote.sessionID ) ? "LAN" : "SecureXnet" );
  502. // Caller is required to transmit a first connectionless packet on net channel address
  503. // to poke through secure handshaking
  504. pChannel->SetTimeout( mm_net_channel_timeout.GetFloat() );
  505. // pChannel->Transmit();
  506. return true;
  507. }
  508. void CX360NetworkMgr::ConnectionPeerUpdateXuid( XUID xuidRemoteOld, XUID xuidRemoteNew )
  509. {
  510. Assert( !xuidRemoteOld != !xuidRemoteNew ); // either of the XUIDs must be NULL
  511. int idxOldRecord = m_arrConnections.Find( xuidRemoteOld );
  512. Assert( idxOldRecord != m_arrConnections.InvalidIndex() );
  513. int idxNewRecord = m_arrConnections.Find( xuidRemoteNew );
  514. // Assert( idxNewRecord == m_arrConnections.InvalidIndex() );
  515. if ( idxOldRecord != m_arrConnections.InvalidIndex() &&
  516. idxNewRecord == m_arrConnections.InvalidIndex() )
  517. {
  518. // Adding an alias to a peer network connection:
  519. // - either found out a host xuid after anonymous connect by NULL xuid
  520. // - or another client migrated to become a new host and adding a NULL xuid alias for that client
  521. ConnectionInfo_t &ci = m_arrConnections.Element( idxOldRecord );
  522. ci.m_xuid = xuidRemoteNew ? xuidRemoteNew : xuidRemoteOld;
  523. ConnectionInfo_t const ciAlias = ci; // need to keep a copy on the stack in case insert reallocates memory
  524. m_arrConnections.Insert( xuidRemoteNew, ciAlias );
  525. DevMsg( "CX360NetworkMgr::ConnectionPeerUpdateXuid: xuidRemote = %llx + %llx, ip = %s, pNetChannel = %p.\n",
  526. xuidRemoteOld, xuidRemoteNew, ciAlias.m_pNetChannel->GetRemoteAddress().ToString(), ciAlias.m_pNetChannel );
  527. }
  528. else if ( idxOldRecord != m_arrConnections.InvalidIndex() &&
  529. idxNewRecord != m_arrConnections.InvalidIndex() &&
  530. !xuidRemoteNew )
  531. {
  532. // Handling a case when client migrated to become a new host and needs a NULL xuid alias,
  533. // but the old host is still registered in network manager with a NULL xuid alias:
  534. // just overwrite the existing NULL alias to point to the new host
  535. ConnectionInfo_t &ciOld = m_arrConnections.Element( idxOldRecord );
  536. ConnectionInfo_t &ciNew = m_arrConnections.Element( idxNewRecord );
  537. DevMsg( "CX360NetworkMgr::ConnectionPeerUpdateXuid: xuidRemote = %llx + %llx, ip = %s, pNetChannel = %p (alias override for host).\n",
  538. xuidRemoteOld, xuidRemoteNew, ciOld.m_pNetChannel->GetRemoteAddress().ToString(), ciOld.m_pNetChannel );
  539. ciNew = ciOld;
  540. }
  541. else
  542. {
  543. DevWarning( "CX360NetworkMgr::ConnectionPeerUpdateXuid: ERROR: xuidRemote = %llx (%s) + %llx (%s)!\n",
  544. xuidRemoteOld, ( ( idxOldRecord != m_arrConnections.InvalidIndex() ) ? "valid" : "missing" ),
  545. xuidRemoteNew, ( ( idxNewRecord != m_arrConnections.InvalidIndex() ) ? "valid" : "missing" ) );
  546. Assert( 0 );
  547. }
  548. }
  549. void CX360NetworkMgr::ConnectionPeerClose( netpacket_t *pktIncoming )
  550. {
  551. IN_ADDR inaddrRemote;
  552. inaddrRemote.s_addr = pktIncoming->from.GetIPNetworkByteOrder();
  553. g_pMatchExtensions->GetIXOnline()->XNetUnregisterInAddr( inaddrRemote );
  554. }
  555. void CX360NetworkMgr::ConnectionPeerClose( XUID xuidRemote )
  556. {
  557. //
  558. // Find the connection record
  559. //
  560. int idx = m_arrConnections.Find( xuidRemote );
  561. if ( !m_arrConnections.IsValidIndex( idx ) )
  562. {
  563. DevWarning( "CX360NetworkMgr::ConnectionPeerClose( xuidRemote = %llx ) failed: not registered!\n",
  564. xuidRemote );
  565. Assert( 0 );
  566. return;
  567. }
  568. ConnectionInfo_t const ci = m_arrConnections[ idx ]; // get a copy
  569. //
  570. // Remove the connection record and host identifier if it refers to the same machine
  571. //
  572. m_arrConnections.RemoveAt( idx );
  573. Assert( ci.m_xuid == xuidRemote || !ci.m_xuid || !xuidRemote ); // NULL record identifies host and only it can be duplicated
  574. m_arrConnections.Remove( ci.m_xuid );
  575. int idxHost = m_arrConnections.Find( 0ull );
  576. if ( m_arrConnections.IsValidIndex( idxHost ) )
  577. {
  578. ConnectionInfo_t const &ciHost = m_arrConnections.Element( idxHost );
  579. if ( ciHost.m_xuid == xuidRemote )
  580. m_arrConnections.RemoveAt( idxHost );
  581. }
  582. //
  583. // Cleanup resources associated with the connection
  584. //
  585. netadr_t inetAddr = ci.m_pNetChannel->GetRemoteAddress();
  586. ci.m_pNetChannel->Shutdown( "" );
  587. delete ci.m_pHandler;
  588. if ( ci.m_xnaddr.inaOnline.s_addr )
  589. {
  590. g_pMatchExtensions->GetIXOnline()->XNetUnregisterInAddr( ci.m_inaddr );
  591. }
  592. DevMsg( "CX360NetworkMgr::ConnectionPeerClose: xuidRemote = %llx, ip = %s, pNetChannel = %p.\n",
  593. ci.m_xuid, inetAddr.ToString(), ci.m_pNetChannel );
  594. }
  595. #endif