1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
6 #include "CrySharedLobbyPacket.h"
7 #include "LAN/CryLANLobby.h"
9 #include "Live/CryLiveLobby.h"
12 #if CRY_PLATFORM_ORBIS
13 #include "PSNOrbis/CryPSN2Lobby.h"
17 #include "Steam/CrySteamLobby.h"
20 #include "DurangoLive/CryDurangoLiveLobby.h"
23 #include <CryGame/IGameFramework.h>
24 #include "INetworkPrivate.h"
25 #include "Protocol/FrameTypes.h"
26 #include <CryMemory/BucketAllocatorImpl.h>
28 #include <CryMath/Random.h>
29 #include <CryCore/Platform/platform_impl.inl>
31 const int LOBBY_KEEP_ALIVE_INTERVAL
= (CryLobbySendInterval
+ 100);
32 const int LOBBY_FORCE_DISCONNECT_TIMER
= 99999999;
34 static const uint8 CONNECTION_COUNTER_MAX
= 255;
36 #if ENCRYPT_LOBBY_PACKETS
37 const char* g_lobbyEncryptionKey
= "gSPyI9\"£$h83H8Uasd73nn()u12gh[[&";
40 #define INVALID_CONNECTION_COOKIE 0
44 SObjectCounters
* g_pObjcnt
= NULL
;
47 #ifdef USE_GLOBAL_BUCKET_ALLOCATOR
48 CCryLobby::CMemAllocator::LobbyBuckets
CCryLobby::CMemAllocator::m_bucketAllocator(NULL
, false);
50 CCryLobby::CMemAllocator::LobbyBuckets
CCryLobby::CMemAllocator::m_bucketAllocator
;
52 ICryLobby
* CCryLobby::m_pLobby
= NULL
;
54 #if defined(_RELEASE) && !defined(DEDICATED_SERVER)
55 #define NO_NETWORK_SECURITY_LOGS
58 #if defined(NO_NETWORK_SECURITY_LOGS)
59 #define SECURE_NET_LOG(...)
61 #define SECURE_NET_LOG NetLog
64 CRYREGISTER_SINGLETON_CLASS(CCryLobby
)
66 CCryLobby::CCryLobby()
71 CCryLobby::~CCryLobby()
75 #if NETWORK_HOST_MIGRATION
76 RemoveHostMigrationEventListener(this);
79 for (a
= 0; a
< eCLS_NumServices
; a
++)
81 InternalSocketDie(ECryLobbyService(a
));
84 #if ENCRYPT_LOBBY_PACKETS
87 gEnv
->pNetwork
->EndCipher(m_cipher
);
94 bool CCryLobby::Initialize(SSystemGlobalEnvironment
& env
, const SSystemInitParams
& initParams
)
98 CryFatalError("Trying to create a lobby when we already have one, this does not end well");
102 g_time
= gEnv
->pTimer
->GetAsyncTime();
104 for (uint32 i
= 0; i
< eCLS_NumServices
; i
++)
106 m_services
[i
] = NULL
;
108 m_task
[i
].cbArg
= NULL
;
110 m_socketServices
[i
].m_socket
= NULL
;
111 m_socketServices
[i
].m_socketListenPort
= 0;
112 m_socketServices
[i
].m_socketConnectPort
= 0;
114 memset(&m_serviceParams
[i
], 0, sizeof(SCryLobbyParameters
));
116 m_servicePacketEnd
[i
] = 0xffff;
119 for (uint32 i
= 0; i
< MAX_LOBBY_TASKS
; i
++)
121 m_serviceTask
[i
].used
= false;
124 for (uint32 i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
126 m_connection
[i
].used
= false;
129 m_userPacketEnd
= 0xffff;
134 m_callbacks
.reserve(10); // pre-reserve space for callback event data
135 m_service
= eCLS_LAN
;
136 m_natType
= eNT_Unknown
;
139 m_gfwlExtras
= new CCryLobbyGFWLExtras
;
144 #if NETWORK_HOST_MIGRATION
145 //m_hostMigrationListeners.reserve(10);
146 AddHostMigrationEventListener(this, "CryLobby", ELPT_Engine
);
149 #if ENCRYPT_LOBBY_PACKETS
152 m_cipher
= gEnv
->pNetwork
->BeginCipher((const uint8
*)g_lobbyEncryptionKey
, 32);
159 ECryLobbyService
CCryLobby::SetLobbyService(ECryLobbyService service
)
163 ECryLobbyService ret
= m_service
;
165 assert(service
< eCLS_NumServices
);
166 #if CRY_PLATFORM_DURANGO || CRY_PLATFORM_ORBIS
167 m_service
= eCLS_Online
;
175 #if NETWORK_HOST_MIGRATION
176 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnInitiate(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
178 NetLog("[Host Migration]: CCryLobby::OnInitiate() started");
180 SHostMigrationInfo_Private
& privateInfo
= static_cast<SHostMigrationInfo_Private
&>(hostMigrationInfo
);
181 privateInfo
.m_lobbyHMStatus
= eLHMS_InitiateMigrate
;
183 NetLog("[Host Migration]: CCryLobby::OnInitiate() finished");
184 return IHostMigrationEventListener::Listener_Done
;
187 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnDisconnectClient(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
189 return IHostMigrationEventListener::Listener_Done
;
192 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnDemoteToClient(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
194 return IHostMigrationEventListener::Listener_Done
;
197 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnPromoteToServer(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
200 CCryMatchMaking
* pMatchMaking
= (CCryMatchMaking
*)GetMatchMaking();
204 SHostMigrationInfo_Private
& privateInfo
= static_cast<SHostMigrationInfo_Private
&>(hostMigrationInfo
);
205 switch (privateInfo
.m_lobbyHMStatus
)
207 case eLHMS_InitiateMigrate
:
208 NetLog("[Host Migration]: CCryLobby::OnPromoteToServer() started");
209 pMatchMaking
->HostMigrationServer(&hostMigrationInfo
);
210 ++privateInfo
.m_lobbyHMStatus
;
212 case eLHMS_Migrating
:
214 done
= pMatchMaking
->IsSessionMigrated(&hostMigrationInfo
);
217 privateInfo
.m_lobbyHMStatus
= eLHMS_InitiateMigrate
;
222 if (hostMigrationInfo
.m_logProgress
|| (done
== true))
224 NetLog("[Host Migration]: CCryLobby::OnPromoteToServer() %s for " PRFORMAT_SH
, ((done
== true) ? "finished" : "waiting"), PRARG_SH(pMatchMaking
->GetSessionHandleFromGameSessionHandle(hostMigrationInfo
.m_session
)));
230 return IHostMigrationEventListener::Listener_Done
;
233 return IHostMigrationEventListener::Listener_Wait
;
236 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnReconnectClient(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
239 CCryMatchMaking
* pMatchMaking
= (CCryMatchMaking
*)GetMatchMaking();
242 SHostMigrationInfo_Private
& privateInfo
= static_cast<SHostMigrationInfo_Private
&>(hostMigrationInfo
);
243 switch (privateInfo
.m_lobbyHMStatus
)
245 case eLHMS_InitiateMigrate
:
246 NetLog("[Host Migration]: CCryLobby::OnReconnectClient() started");
247 ++privateInfo
.m_lobbyHMStatus
;
249 case eLHMS_Migrating
:
250 done
= pMatchMaking
->IsSessionMigrated(&hostMigrationInfo
);
255 if (hostMigrationInfo
.m_logProgress
|| (done
== true))
257 NetLog("[Host Migration]: CCryLobby::OnReconnectClient() %s for " PRFORMAT_SH
, ((done
== true) ? "finished" : "waiting"), PRARG_SH(pMatchMaking
->GetSessionHandleFromGameSessionHandle(hostMigrationInfo
.m_session
)));
262 pMatchMaking
->OnReconnectClient(hostMigrationInfo
);
268 return IHostMigrationEventListener::Listener_Done
;
271 return IHostMigrationEventListener::Listener_Wait
;
274 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnFinalise(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
276 return IHostMigrationEventListener::Listener_Done
;
279 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnTerminate(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
281 return IHostMigrationEventListener::Listener_Done
;
284 IHostMigrationEventListener::EHostMigrationReturn
CCryLobby::OnReset(SHostMigrationInfo
& hostMigrationInfo
, HMStateType
& state
)
286 return IHostMigrationEventListener::Listener_Done
;
290 void CCryLobby::InviteAccepted(ECryLobbyService service
, uint32 user
, CrySessionID sessionID
, ECryLobbyError error
)
292 UCryLobbyEventData eventData
;
293 SCryLobbyInviteAcceptedData inviteData
;
295 eventData
.pInviteAcceptedData
= &inviteData
;
296 inviteData
.m_service
= service
;
297 inviteData
.m_user
= user
;
298 inviteData
.m_id
= sessionID
;
299 inviteData
.m_error
= error
;
300 DispatchEvent(eCLSE_InviteAccepted
, eventData
);
303 void CCryLobby::InviteAccepted(ECryLobbyService service
, uint32 user
, CryUserID userID
, ECryLobbyError error
, ECryLobbyInviteType inviteType
)
305 UCryLobbyEventData eventData
;
306 SCryLobbyUserInviteAcceptedData inviteData
;
308 eventData
.pUserInviteAcceptedData
= &inviteData
;
309 inviteData
.m_service
= service
;
310 inviteData
.m_user
= user
;
311 inviteData
.m_inviterId
= userID
;
312 inviteData
.m_error
= error
;
313 inviteData
.m_type
= inviteType
;
314 DispatchEvent(eCLSE_UserInviteAccepted
, eventData
);
317 uint32
CCryLobby::GetDisconnectTimeOut()
319 const CNetCVars
* pNetCVars
= GetNetCVars();
323 if (gEnv
->pSystem
->IsDevMode())
325 if (pNetCVars
->InactivityTimeoutDevmode
> 0.0f
)
327 return (uint32
)(1000.0f
* pNetCVars
->InactivityTimeoutDevmode
);
332 if (pNetCVars
->InactivityTimeout
> 0.0f
)
334 return (uint32
)(1000.0f
* pNetCVars
->InactivityTimeout
);
339 return CryLobbyTimeOut
;
342 void CCryLobby::LogPacketsInBuffer(const uint8
* pBuffer
, uint32 size
)
344 #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
345 CCrySharedLobbyPacket packet
;
346 SCryLobbyPacketHeader
* pPacketHeader
= packet
.GetLobbyPacketHeader();
347 SCryLobbyPacketDataHeader
* pDataHeader
= packet
.GetLobbyPacketDataHeader();
349 packet
.SetReadBuffer(pBuffer
, size
);
350 pPacketHeader
->reliable
= true; // No point reading whole header for this log
351 packet
.SetReadBufferPos(CryLobbyPacketReliablePacketHeaderSize
);
353 while (packet
.GetReadBufferPos() < size
)
355 packet
.ReadDataHeader();
356 uint32 encodedPacketType
= pDataHeader
->lobbyPacketType
;
357 DecodePacketDataHeader(&packet
);
358 NetLog(" packet %d (%d) size %d", pDataHeader
->lobbyPacketType
, encodedPacketType
, pDataHeader
->dataSize
);
359 packet
.SetReadBufferPos(packet
.GetReadBufferPos() + pDataHeader
->dataSize
);
361 #endif // #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
364 void CCryLobby::Tick(bool flush
)
366 if (gEnv
->IsEditor() || (gEnv
->pSystem
&& gEnv
->pSystem
->IsQuitting()))
371 ProcessCachedPacketBuffer();
373 uint32 lastFrameTime
= 0;
374 uint32 disconnectTimeOut
= GetDisconnectTimeOut();
375 uint32 CryLobbyKeepAliveInterval
= LOBBY_KEEP_ALIVE_INTERVAL
;
377 g_time
= gEnv
->pTimer
->GetAsyncTime();
381 lastFrameTime
= (uint32
)(g_time
.GetMilliSecondsAsInt64() - m_lastTickTime
.GetMilliSecondsAsInt64());
382 if (lastFrameTime
> CryLobbySendInterval
)
384 NetLog("CCryLobby::TimerCallback() long frame detected, lastFrameTime=%u", lastFrameTime
);
385 // Guard against very long frames that can cause sends to time out even before they have started.
386 lastFrameTime
= CryLobbySendInterval
;
390 #if USE_LOBBY_REMOTE_CONNECTIONS
391 for (uint32 i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
393 SConnection
* pConnection
= &m_connection
[i
];
395 if (pConnection
->used
)
397 bool doneSend
= false;
399 pConnection
->timeSinceSend
+= lastFrameTime
;
400 pConnection
->timeSinceRecv
+= lastFrameTime
;
402 switch (pConnection
->state
)
404 case eCLCS_NotConnected
:
405 if (pConnection
->refCount
== 0)
407 SECURE_NET_LOG("[lobby] Release connection " PRFORMAT_LCINFO
, PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
416 if (pConnection
->timeSinceSend
>= CryLobbySendInterval
)
418 const uint32 MaxBufferSize
= CryLobbyPacketHeaderSize
419 #if RESET_CONNECTED_CONNECTION
420 + CryLobbyPacketUINT64Size
;
423 uint8 buffer
[MaxBufferSize
];
424 CCrySharedLobbyPacket packet
;
426 packet
.SetWriteBuffer(buffer
, MaxBufferSize
);
428 packet
.StartWrite(eLobbyPT_ConnectionRequest
, false);
430 #if RESET_CONNECTED_CONNECTION
431 SECURE_NET_LOG("[Lobby] Sending connection request with cookie %llx connection " PRFORMAT_LCINFO
, pConnection
->sendCookie
, PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
432 packet
.WriteUINT64(pConnection
->sendCookie
);
435 if (Send(&packet
, pConnection
->addr
, i
, NULL
) != eSE_Ok
)
437 SECURE_NET_LOG("[Lobby] Failed to send setting pending connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
438 pConnection
->state
= eCLCS_NotConnected
;
445 case eCLCS_Connected
:
446 if (((pConnection
->timeSinceRecv
> CryLobbyKeepAliveInterval
) && (pConnection
->timeSinceSend
> CryLobbyKeepAliveInterval
)) ||
447 ((pConnection
->timeSinceSend
>= CryLobbySendInterval
) && (pConnection
->ping
.times
[NUM_LOBBY_PINGS
- 1] == CRYLOBBY_INVALID_PING
)) ||
448 (pConnection
->timeSinceSend
>= CryLobbyInGameSendInterval
))
450 const uint32 MaxBufferSize
= CryLobbyPacketHeaderSize
+ CryLobbyPacketUINT64Size
;
451 uint8 buffer
[MaxBufferSize
];
452 CCrySharedLobbyPacket packet
;
454 packet
.SetWriteBuffer(buffer
, MaxBufferSize
);
456 packet
.StartWrite(eLobbyPT_Ping
, false);
457 packet
.WriteUINT64(gEnv
->pTimer
->GetAsyncTime().GetMilliSecondsAsInt64());
459 if (Send(&packet
, pConnection
->addr
, i
, NULL
) != eSE_Ok
)
461 SECURE_NET_LOG("[Lobby] Failed to send setting connected connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
462 pConnection
->state
= eCLCS_NotConnected
;
466 if (pConnection
->refCount
== 0)
468 // There are no references to this connection.
469 if (pConnection
->dataQueue
.Empty())
471 pConnection
->disconnectTimer
+= lastFrameTime
;
473 if (pConnection
->disconnectTimer
> disconnectTimeOut
)
475 // It hasn't been in use for a while
476 SECURE_NET_LOG("[Lobby] No references to connection setting connected connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
477 pConnection
->state
= eCLCS_NotConnected
;
482 // It's still in use so reset counter.
483 pConnection
->disconnectTimer
= 0;
488 pConnection
->disconnectTimer
= 0;
494 if (pConnection
->timeSinceRecv
> disconnectTimeOut
)
496 // It hasn't been in use for a while
497 if (pConnection
->state
!= eCLCS_NotConnected
)
499 SECURE_NET_LOG("[Lobby] Connection to " PRFORMAT_LCINFO
" has timed out (timeSinceRecv %u disconnectTimeOut %u) setting to eCLCS_NotConnected", PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
), pConnection
->timeSinceRecv
, disconnectTimeOut
);
500 pConnection
->state
= eCLCS_NotConnected
;
504 if (pConnection
->dataQueue
.Empty() && (pConnection
->reliableBuildPacket
.GetWriteBufferPos() > 0))
506 AddReliablePacketToSendQueue(i
, &pConnection
->reliableBuildPacket
);
509 if (!pConnection
->dataQueue
.Empty())
511 if ((pConnection
->timeSinceSend
>= CryLobbySendInterval
) || flush
)
513 SConnection::SData
& data
= pConnection
->dataQueue
.Front();
515 #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
516 CCrySharedLobbyPacket packetInfo
;
518 packetInfo
.SetReadBuffer((const uint8
*)MemGetPtr(data
.data
), data
.dataSize
);
520 packetInfo
.ReadPacketHeader();
522 SECURE_NET_LOG("[lobby] Send reliable connection " PRFORMAT_LCINFO
" from " PRFORMAT_UID
" counter %d size %d",
523 PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
), PRARG_UID(packetInfo
.GetLobbyPacketHeader()->fromUID
), data
.counter
, data
.dataSize
);
525 LogPacketsInBuffer((uint8
*)MemGetPtr(data
.data
), data
.dataSize
);
526 #endif // #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
530 // Data hasn't been acknowledged so try sending again
531 SSocketService
* pSocketService
= GetCorrectSocketServiceForAddr(pConnection
->addr
);
532 if (pSocketService
->m_socket
)
534 if (pSocketService
->m_socket
->Send(EncryptPacket((uint8
*)MemGetPtr(data
.data
), data
.dataSize
), data
.dataSize
, pConnection
->addr
) != eSE_Ok
)
536 SECURE_NET_LOG("[Lobby] Failed to send setting connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
537 pConnection
->state
= eCLCS_NotConnected
;
542 if ((pConnection
->timeSinceRecv
> disconnectTimeOut
) || (pConnection
->state
== eCLCS_NotConnected
))
545 OnError(pConnection
->addr
, eSE_UnreachableAddress
);
550 if (pConnection
->state
== eCLCS_Freeing
)
552 SECURE_NET_LOG("[Lobby] Setting freeing connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
553 pConnection
->state
= eCLCS_NotConnected
;
559 pConnection
->timeSinceSend
= 0;
563 #endif // USE_LOBBY_REMOTE_CONNECTIONS
565 if (m_mutex
.TryLock())
567 m_fromGameQueue
.Flush(false);
573 // We're flushing, so no need to tick services or reset the timer
577 // Tick all lobby services.
578 // Things like invite notifications for a service still need to be processed even if currently using a different service
579 for (uint32 i
= 0; i
< eCLS_NumServices
; i
++)
583 m_services
[i
]->Tick(g_time
);
587 m_lastTickTime
= g_time
;
590 void CCryLobby::InitialiseServiceCB(ECryLobbyError error
, CCryLobby
* lobby
, ECryLobbyService service
)
592 if (error
!= eCLE_Success
)
594 lobby
->m_services
[service
] = NULL
;
597 if (lobby
->m_task
[service
].cb
)
599 lobby
->m_task
[service
].cb(service
, error
, lobby
->m_task
[service
].cbArg
);
603 void CCryLobby::TerminateServiceCB(ECryLobbyError error
, CCryLobby
* lobby
, ECryLobbyService service
)
605 // Remove our reference to the service. It will be deleted when all references are gone.
606 lobby
->m_services
[service
] = NULL
;
608 lobby
->CheckFreeGlobalResources();
610 if (lobby
->m_task
[service
].cb
)
612 lobby
->m_task
[service
].cb(service
, error
, lobby
->m_task
[service
].cbArg
);
616 #define MAX_IP_EXPECTED (16)
617 #define MAX_ADDRESS_SIZE (MAX_IP_EXPECTED + 6 + 1)
619 void FixPortBinding(TNetAddress
& defaultBind
, int port
)
621 #if CRY_PLATFORM_WINDOWS // On windows we should check the sv_bind variable and attempt to play nice and bind to the address requested
622 CNetAddressResolver
* pResolver
= CCryLobby::GetResolver();
626 char address
[MAX_ADDRESS_SIZE
];
628 cry_sprintf(address
, "0.0.0.0:%d", port
);
630 ICVar
* pCVar
= gEnv
->pConsole
->GetCVar("sv_bind");
631 if (pCVar
&& pCVar
->GetString())
633 if (strlen(pCVar
->GetString()) <= MAX_IP_EXPECTED
)
635 cry_sprintf(address
, "%s:%d", pCVar
->GetString(), port
);
639 NetLog("Address to bind '%s' does not appear to be an IP address", pCVar
->GetString());
643 CNameRequestPtr pReq
= pResolver
->RequestNameLookup(address
);
645 if (pReq
->GetResult() != eNRR_Succeeded
)
647 NetLog("Name resolution for '%s' failed - binding to 0.0.0.0", address
);
651 defaultBind
= pReq
->GetAddrs()[0];
655 #endif // CRY_PLATFORM_WINDOWS
658 void CCryLobby::InternalSocketCreate(ECryLobbyService service
)
660 SSocketService
* pSocketService
= GetCorrectSocketService(service
);
662 CRY_ASSERT(service
< eCLS_NumServices
, "Illegal service specified");
663 CRY_ASSERT(m_services
[service
] != NULL
, "Tried to create a socket for a non existant service.");
665 pSocketService
->m_socketConnectPort
= 0;
666 pSocketService
->m_socketListenPort
= 0;
668 if (m_services
[service
] != NULL
)
670 m_services
[service
]->GetSocketPorts(pSocketService
->m_socketConnectPort
, pSocketService
->m_socketListenPort
);
673 uint16 port
= pSocketService
->m_socketListenPort
;
674 TNetAddress defaultBind
= TNetAddress(SIPv4Addr(0, port
));
675 FixPortBinding(defaultBind
, port
);
677 ISocketIOManager
* pSocketIOManager
= GetExternalSocketIOManager();
678 uint32 flags
= eSF_Online
;
680 if (service
== eCLS_LAN
)
682 pSocketIOManager
= GetInternalSocketIOManager();
683 flags
= (eSF_BroadcastSend
| eSF_BroadcastReceive
);
686 if (pSocketIOManager
&& !pSocketService
->m_socket
)
688 InternalSocketFree(service
);
690 NetLog("[Lobby] Creating socket on port %u (service [%s], socket manager [%s])", port
, (service
== eCLS_LAN
) ? "LAN" : "Online", pSocketIOManager
->GetName());
691 pSocketService
->m_socket
= pSocketIOManager
->CreateDatagramSocket(defaultBind
, flags
);
693 if (!pSocketService
->m_socket
)
695 NetLog("[Lobby] Failed to create socket on port %u", port
);
696 if ((gEnv
->IsDedicated() == false) || ((gEnv
->IsClient() == true) && (gEnv
->bServer
== false)))
698 // If we are not a dedicated server (Which should always use the port specified in the cfg file) and we fail to create the socket
699 // try to create on some different ports.
701 for (uint32 i
= 1; i
< MAX_SOCKET_PORTS_TRY
; i
++)
704 defaultBind
= TNetAddress(SIPv4Addr(0, port
));
705 FixPortBinding(defaultBind
, port
);
706 NetLog("[Lobby] Creating socket on port %u", port
);
707 pSocketService
->m_socket
= pSocketIOManager
->CreateDatagramSocket(defaultBind
, flags
);
709 if (pSocketService
->m_socket
)
715 NetLog("[Lobby] Failed to create socket on port %u", port
);
721 if (pSocketService
->m_socket
)
723 NetLog("[Lobby] Created socket on port %u", port
);
724 pSocketService
->m_socket
->RegisterListener(this);
725 pSocketService
->m_socketListenPort
= port
;
726 m_serviceParams
[service
].m_listenPort
= port
;
727 if (m_services
[service
] != NULL
)
729 m_services
[service
]->OnInternalSocketChanged(pSocketService
->m_socket
);
734 CryWarning(VALIDATOR_MODULE_ONLINE
, VALIDATOR_ERROR
,
735 "[Lobby] Socket could not be created, check firewall or try a different port. Connecting to network games may fail if not fixed.");
740 void CCryLobby::InternalSocketDie(ECryLobbyService service
)
742 CRY_ASSERT(service
< eCLS_NumServices
, "Illegal service specified");
743 SSocketService
* pSocketService
= GetCorrectSocketService(service
);
744 ISocketIOManager
* pSocketIOManager
= GetExternalSocketIOManager();
745 if (service
== eCLS_LAN
)
747 pSocketIOManager
= GetInternalSocketIOManager();
750 if (pSocketIOManager
&& pSocketService
->m_socket
)
752 pSocketService
->m_socket
->UnregisterListener(this);
753 pSocketIOManager
->FreeDatagramSocket(pSocketService
->m_socket
);
754 pSocketService
->m_socket
= NULL
;
757 if (m_services
[service
])
759 m_services
[service
]->OnInternalSocketChanged(pSocketService
->m_socket
);
763 void CCryLobby::InternalSocketFree(ECryLobbyService service
)
765 SSocketService
* pSocketService
= GetCorrectSocketService(service
);
766 if (pSocketService
->m_socket
)
768 InternalSocketDie(service
);
772 ECryLobbyError
CCryLobby::CheckAllocGlobalResources()
774 g_pObjcnt
= &((INetworkPrivate
*)gEnv
->pNetwork
)->GetObjectCounters();
778 void CCryLobby::CheckFreeGlobalResources()
782 for (i
= 0; i
< eCLS_NumServices
; i
++)
790 if (i
== eCLS_NumServices
)
794 for (i
= 0; i
< MAX_LOBBY_TASKS
; i
++)
796 m_serviceTask
[i
].used
= false;
799 for (i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
804 for (a
= 0; a
< eCLS_NumServices
; a
++)
806 InternalSocketDie(ECryLobbyService(a
));
811 CryLobbyTaskID
CCryLobby::CreateTask()
813 for (uint32 i
= 0; i
< MAX_LOBBY_TASKS
; i
++)
815 if (!m_serviceTask
[i
].used
)
817 m_serviceTask
[i
].used
= true;
818 #if ENABLE_CRYLOBBY_DEBUG_TESTS
819 m_serviceTask
[i
].startTaskTime
= 0LL;
820 m_serviceTask
[i
].tickTaskTime
= 0LL;
821 m_serviceTask
[i
].generateErrorDone
= false;
822 m_serviceTask
[i
].startTaskTimerStarted
= false;
823 m_serviceTask
[i
].startTaskDone
= false;
824 m_serviceTask
[i
].tickTaskTimerStarted
= false;
825 m_serviceTask
[i
].tickTaskDone
= false;
831 return CryLobbyInvalidTaskID
;
834 void CCryLobby::ReleaseTask(CryLobbyTaskID id
)
836 m_serviceTask
[id
].used
= false;
839 #if ENABLE_CRYLOBBY_DEBUG_TESTS
840 bool CCryLobby::DebugGenerateError(CryLobbyTaskID id
, ECryLobbyError
& error
)
842 if (CLobbyCVars::Get().cldEnable
)
844 SServiceTask
* pTask
= &m_serviceTask
[id
];
846 if (!pTask
->generateErrorDone
)
848 pTask
->generateErrorDone
= true;
850 if (cry_random(0, 99) < CLobbyCVars::Get().cldErrorPercentage
)
852 NetLog("[Lobby] Generating random eCLE_TimeOut on task %u", id
);
853 error
= eCLE_TimeOut
;
862 bool CCryLobby::DebugOKToStartTaskRunning(CryLobbyTaskID id
)
864 int minDelay
= CLobbyCVars::Get().cldMinDelayTime
;
865 int maxDelay
= CLobbyCVars::Get().cldMaxDelayTime
;
867 if (CLobbyCVars::Get().cldEnable
&& (minDelay
>= 0) && (maxDelay
> minDelay
))
869 SServiceTask
* pTask
= &m_serviceTask
[id
];
871 if (!pTask
->startTaskTimerStarted
)
874 int64 addMilliSeconds
;
876 addMilliSeconds
= cry_random(minDelay
, maxDelay
);
878 addTime
.SetMilliSeconds(addMilliSeconds
);
880 pTask
->startTaskTimerStarted
= true;
881 pTask
->startTaskDone
= false;
882 pTask
->startTaskTime
= g_time
+ addTime
;
884 NetLog("[Lobby] Delay start task %u for %" PRIi64
" milliseconds", id
, addMilliSeconds
);
889 NetLog("[Lobby] Delayed task %u started", id
);
895 bool CCryLobby::DebugTickCallStartTaskRunning(CryLobbyTaskID id
)
897 if (CLobbyCVars::Get().cldEnable
)
899 SServiceTask
* pTask
= &m_serviceTask
[id
];
901 if (pTask
->startTaskTimerStarted
&& !pTask
->startTaskDone
)
903 if (g_time
> pTask
->startTaskTime
)
905 pTask
->startTaskDone
= true;
914 bool CCryLobby::DebugOKToTickTask(CryLobbyTaskID id
, bool running
)
916 int minDelay
= CLobbyCVars::Get().cldMinDelayTime
;
917 int maxDelay
= CLobbyCVars::Get().cldMaxDelayTime
;
919 if (CLobbyCVars::Get().cldEnable
&& (minDelay
>= 0) && (maxDelay
> minDelay
))
921 SServiceTask
* pTask
= &m_serviceTask
[id
];
923 if (running
&& !pTask
->startTaskDone
)
925 if (!pTask
->tickTaskTimerStarted
)
928 int64 addMilliSeconds
;
930 addMilliSeconds
= cry_random(minDelay
, maxDelay
);
932 addTime
.SetMilliSeconds(addMilliSeconds
);
934 pTask
->tickTaskTimerStarted
= true;
935 pTask
->tickTaskTime
= g_time
+ addTime
;
937 NetLog("[Lobby] Delay start ticking task %u for %" PRIi64
" milliseconds", id
, addMilliSeconds
);
943 if (g_time
> pTask
->tickTaskTime
)
945 if (!pTask
->tickTaskDone
)
947 NetLog("[Lobby] Delayed task %u ticking", id
);
949 pTask
->tickTaskDone
= true;
966 ECryLobbyError
CCryLobby::Initialise(ECryLobbyService service
, ECryLobbyServiceFeatures features
, CryLobbyConfigurationCallback cfgCb
, CryLobbyCallback cb
, void* cbArg
)
970 ECryLobbyError error
= eCLE_Success
;
971 if (features
& eCLSO_Base
)
973 error
= CheckAllocGlobalResources();
976 assert(service
>= 0 && service
< eCLS_NumServices
);
978 if (error
== eCLE_Success
)
983 //#if !defined(_RELEASE) && !defined(DEDICATED_SERVER) && !defined(PURE_CLIENT)
985 if (m_services
[eCLS_LAN
] == NULL
)
987 m_services
[eCLS_LAN
] = new CCryLANLobbyService(this, service
);
989 if (!m_services
[eCLS_LAN
])
991 error
= eCLE_OutOfMemory
;
995 error
= eCLE_ServiceNotSupported
;
1001 if (m_services
[eCLS_Online
] == NULL
)
1004 if (CLobbyCVars::Get().useSteamAsOnlineLobby
)
1006 m_services
[eCLS_Online
] = new CCrySteamLobbyService(this, service
);
1008 if (!m_services
[eCLS_Online
])
1010 error
= eCLE_OutOfMemory
;
1015 error
= eCLE_ServiceNotSupported
;
1019 m_services
[eCLS_Online
] = new CCryLiveLobbyService(this, service
);
1021 if (!m_services
[eCLS_Online
])
1023 error
= eCLE_OutOfMemory
;
1026 m_services
[eCLS_Online
] = new CCryPSNLobbyService(this, service
);
1028 if (!m_services
[eCLS_Online
])
1030 error
= eCLE_OutOfMemory
;
1032 #elif USE_DURANGOLIVE
1033 m_services
[eCLS_Online
] = new CCryDurangoLiveLobbyService(this, service
);
1035 if (!m_services
[eCLS_Online
])
1037 error
= eCLE_OutOfMemory
;
1040 m_services
[eCLS_Online
] = NULL
;
1041 error
= eCLE_ServiceNotSupported
;
1048 if (error
== eCLE_Success
)
1050 m_task
[service
].cb
= cb
;
1051 m_task
[service
].cbArg
= cbArg
;
1052 this->m_configCB
= cfgCb
;
1054 error
= m_services
[service
]->Initialise(features
, (features
& eCLSO_Base
) ? InitialiseServiceCB
: NULL
);
1056 if (error
== eCLE_Success
)
1058 if (features
& eCLSO_Base
)
1060 FROM_GAME_TO_LOBBY(&CCryLobbyService::CreateSocketNT
, m_services
[service
].get());
1065 // Task didn't start so remove our reference to the service
1066 m_services
[service
] = NULL
;
1071 if ((error
== eCLE_Success
) && (features
& eCLSO_Base
))
1073 // Final step, initialise lobby parameters
1074 m_services
[service
]->GetSocketPorts(m_serviceParams
[service
].m_connectPort
, m_serviceParams
[service
].m_listenPort
);
1077 CryLog("[Lobby] Initialise service %d error %d\n", service
, error
);
1082 ECryLobbyError
CCryLobby::Terminate(ECryLobbyService service
, ECryLobbyServiceFeatures features
, CryLobbyCallback cb
, void* cbArg
)
1085 ECryLobbyError error
;
1087 if (m_services
[service
])
1089 m_task
[service
].cb
= cb
;
1090 m_task
[service
].cbArg
= cbArg
;
1092 error
= m_services
[service
]->Terminate(features
, (features
& eCLSO_Base
) ? TerminateServiceCB
: NULL
);
1094 if (features
& eCLSO_Base
)
1096 m_services
[service
] = NULL
;
1101 error
= eCLE_NotInitialised
;
1105 if (features
& eCLSO_Base
)
1107 CheckFreeGlobalResources();
1110 CryLog("[Lobby] Terminate service %d error %d\n", service
, error
);
1115 ECryLobbyError
CCryLobby::ProcessEvents()
1117 if (m_safetyToGameMutex
.TryLock())
1119 m_toGameQueue
.Flush(false);
1120 m_safetyToGameMutex
.Unlock();
1121 return eCLE_Success
;
1124 return eCLE_SuccessContinue
;
1127 CryLobbyConnectionID
CCryLobby::CreateConnection(const TNetAddress
& address
)
1129 #if USE_LOBBY_REMOTE_CONNECTIONS
1130 for (uint32 i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
1132 if (!m_connection
[i
].used
)
1134 SConnection
* pConnection
= &m_connection
[i
];
1136 #if RESET_CONNECTED_CONNECTION
1137 pConnection
->sendCookie
= gEnv
->pTimer
->GetAsyncTime().GetValue();
1138 pConnection
->recvCookie
= INVALID_CONNECTION_COOKIE
;
1141 pConnection
->timeSinceSend
= 0;
1142 pConnection
->timeSinceRecv
= 0;
1143 pConnection
->disconnectTimer
= 0;
1144 pConnection
->addr
= address
;
1145 pConnection
->state
= eCLCS_Pending
;
1146 pConnection
->refCount
= 0;
1147 pConnection
->counterIn
= 0;
1148 pConnection
->counterOut
= 0;
1149 pConnection
->used
= true;
1150 pConnection
->reliableBuildPacket
.SetWriteBuffer(pConnection
->reliableBuildPacketBuffer
, MAX_LOBBY_PACKET_SIZE
);
1152 pConnection
->ping
.aveTime
= CRYLOBBY_INVALID_PING
;
1153 pConnection
->ping
.currentTime
= 0;
1155 for (uint32 j
= 0; j
< NUM_LOBBY_PINGS
; j
++)
1157 pConnection
->ping
.times
[j
] = CRYLOBBY_INVALID_PING
;
1160 ECryLobbyService service
= GetCorrectSocketServiceTypeForAddr(address
);
1161 if (!GetInternalSocket(service
))
1163 NetLog("[Lobby] Socket was not previously ready, trying again");
1164 InternalSocketCreate(service
);
1167 SECURE_NET_LOG("[lobby] Create reliable connection " PRFORMAT_LCINFO
, PRARG_LCINFO(CryLobbyConnectionID(i
), pConnection
->addr
));
1172 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1174 return CryLobbyInvalidConnectionID
;
1177 CryLobbyConnectionID
CCryLobby::FindConnection(const TNetAddress
& address
)
1179 #if USE_LOBBY_REMOTE_CONNECTIONS
1180 for (uint32 i
= 0; i
< MAX_LOBBY_CONNECTIONS
; i
++)
1182 if (m_connection
[i
].used
&& (m_connection
[i
].addr
== address
))
1187 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1189 return CryLobbyInvalidConnectionID
;
1192 void CCryLobby::ConnectionAddRef(CryLobbyConnectionID c
)
1194 #if USE_LOBBY_REMOTE_CONNECTIONS
1195 if (c
!= CryLobbyInvalidConnectionID
)
1197 SConnection
* pConnection
= &m_connection
[c
];
1199 if (pConnection
->used
)
1201 SECURE_NET_LOG("RefCount of connection " PRFORMAT_LCINFO
" is incrementing, %u->%u. Thread #%" PRI_THREADID
, PRARG_LCINFO(c
, pConnection
->addr
), pConnection
->refCount
, pConnection
->refCount
+ 1u, CryGetCurrentThreadId());
1203 pConnection
->refCount
++;
1206 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1209 bool CCryLobby::KeepPacketAfterDisconnect(uint32 packetType
)
1211 return ((packetType
== eLobbyPT_SessionDeleteRemoteConnection
) ||
1212 (packetType
== eLobbyPT_SessionRequestJoinResult
));
1215 void CCryLobby::ConnectionRemoveRef(CryLobbyConnectionID c
)
1217 #if USE_LOBBY_REMOTE_CONNECTIONS
1218 if (c
!= CryLobbyInvalidConnectionID
)
1220 SConnection
* pConnection
= &m_connection
[c
];
1222 if (pConnection
->used
)
1224 if (pConnection
->refCount
> 0)
1226 SECURE_NET_LOG("RefCount of connection " PRFORMAT_LCINFO
" is decrementing, %u->%d. Thread #%" PRI_THREADID
, PRARG_LCINFO(c
, pConnection
->addr
), pConnection
->refCount
, pConnection
->refCount
- 1u, CryGetCurrentThreadId());
1228 pConnection
->refCount
--;
1230 if (pConnection
->refCount
== 0)
1232 if (pConnection
->reliableBuildPacket
.GetWriteBufferPos() > 0)
1234 AddReliablePacketToSendQueue(c
, &pConnection
->reliableBuildPacket
);
1237 // We only need to keep eLobbyPT_SessionDeleteRemoteConnection in the send queue so the other end knows we are leaving.
1238 // All other packets should be removed as they are not important now.
1239 NetLog("[Lobby] %u packets in send queue", pConnection
->dataQueue
.Size());
1240 pConnection
->counterOut
-= (uint8
) pConnection
->dataQueue
.Size();
1242 if (!pConnection
->dataQueue
.Empty())
1244 uint32 numCheck
= pConnection
->dataQueue
.Size();
1246 for (uint32 i
= 0; i
< numCheck
; i
++)
1248 SConnection::SData
& data
= pConnection
->dataQueue
.Front();
1249 uint8
* pData
= (uint8
*)MemGetPtr(data
.data
);
1250 CCrySharedLobbyPacket packet
;
1252 SCryLobbyPacketDataHeader
* pDataHeader
= packet
.GetLobbyPacketDataHeader();
1254 pConnection
->dataQueue
.Pop();
1256 while (GetNextPacketFromBuffer(pData
, data
.dataSize
, dataPos
, &packet
))
1258 #if !defined(EXCLUDE_NORMAL_LOG)
1259 uint32 encodedPacketType
= pDataHeader
->lobbyPacketType
;
1261 DecodePacketDataHeader(&packet
);
1263 if (KeepPacketAfterDisconnect(pDataHeader
->lobbyPacketType
))
1265 NetLog("[Lobby] Keep packet %u (%u) Size %u", pDataHeader
->lobbyPacketType
, encodedPacketType
, pDataHeader
->dataSize
);
1266 EncodePacketDataHeader(&packet
);
1267 AddPacketToReliableBuildPacket(c
, &packet
);
1271 NetLog("[Lobby] Remove packet %u Size %u", pDataHeader
->lobbyPacketType
, pDataHeader
->dataSize
);
1279 if (pConnection
->reliableBuildPacket
.GetWriteBufferPos() > 0)
1281 AddReliablePacketToSendQueue(c
, &pConnection
->reliableBuildPacket
);
1283 // Put connection into freeing state
1284 // Any sends in queue will still try and send and no new sends will be accepted
1285 pConnection
->state
= eCLCS_Freeing
;
1289 SECURE_NET_LOG("[lobby] Release connection " PRFORMAT_LCINFO
, PRARG_LCINFO(c
, pConnection
->addr
));
1297 #if !defined(_RELEASE)
1298 CryFatalError("RefCount of connection " PRFORMAT_LCINFO
" is trying to drop below 0! Thread #%" PRI_THREADID
".", PRARG_LCINFO(c
, pConnection
->addr
), CryGetCurrentThreadId());
1300 SECURE_NET_LOG("RefCount of connection " PRFORMAT_LCINFO
" is trying to drop below 0! Thread #%" PRI_THREADID
".", PRARG_LCINFO(c
, pConnection
->addr
), CryGetCurrentThreadId());
1305 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1308 bool CCryLobby::ConnectionHasReference(CryLobbyConnectionID c
)
1310 #if USE_LOBBY_REMOTE_CONNECTIONS
1311 if (c
!= CryLobbyInvalidConnectionID
)
1313 SConnection
* pConnection
= &m_connection
[c
];
1315 if (pConnection
->used
)
1317 return pConnection
->refCount
> 0;
1325 void CCryLobby::ConnectionSetState(CryLobbyConnectionID c
, ECryLobbyConnectionState state
)
1327 #if USE_LOBBY_REMOTE_CONNECTIONS
1328 if (c
!= CryLobbyInvalidConnectionID
)
1330 SConnection
* pConnection
= &m_connection
[c
];
1332 if (pConnection
->used
)
1334 pConnection
->state
= state
;
1337 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1340 ECryLobbyConnectionState
CCryLobby::ConnectionGetState(CryLobbyConnectionID c
)
1342 #if USE_LOBBY_REMOTE_CONNECTIONS
1343 if (c
!= CryLobbyInvalidConnectionID
)
1345 SConnection
* pConnection
= &m_connection
[c
];
1347 if (pConnection
->used
)
1349 return pConnection
->state
;
1352 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1354 return eCLCS_NotConnected
;
1357 void CCryLobby::FreeConnection(CryLobbyConnectionID c
)
1359 #if USE_LOBBY_REMOTE_CONNECTIONS
1360 if (c
!= CryLobbyInvalidConnectionID
)
1362 SConnection
* connection
= &m_connection
[c
];
1364 if (connection
->used
)
1366 connection
->used
= false;
1368 while (!connection
->dataQueue
.Empty())
1370 SConnection::SData
& data
= connection
->dataQueue
.Front();
1373 connection
->dataQueue
.Pop();
1377 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1380 bool CCryLobby::ConnectionFromAddress(CryLobbyConnectionID
* connection
, const TNetAddress
& address
)
1382 *connection
= FindConnection(address
);
1384 return *connection
!= CryLobbyInvalidConnectionID
;
1387 bool CCryLobby::AddressFromConnection(TNetAddress
& address
, CryLobbyConnectionID c
)
1389 #if USE_LOBBY_REMOTE_CONNECTIONS
1390 assert(c
== CryLobbyInvalidConnectionID
|| c
< MAX_LOBBY_CONNECTIONS
);
1392 if (c
< MAX_LOBBY_CONNECTIONS
)
1394 SConnection
* connection
= &m_connection
[c
];
1396 if (connection
->used
)
1398 address
= connection
->addr
;
1402 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1407 bool CCryLobby::SetConnectionAddress(CryLobbyConnectionID c
, TNetAddress
& address
)
1409 #if USE_LOBBY_REMOTE_CONNECTIONS
1410 if (c
!= CryLobbyInvalidConnectionID
)
1412 SConnection
* connection
= &m_connection
[c
];
1414 if (connection
->used
)
1416 connection
->addr
= address
;
1420 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1425 void CCryLobby::FlushMessageQueue()
1430 bool CCryLobby::AddReliablePacketToSendQueue(CryLobbyConnectionID connectionID
, CCryLobbyPacket
* pPacket
)
1432 #if USE_LOBBY_REMOTE_CONNECTIONS
1433 SConnection
* pConnection
= &m_connection
[connectionID
];
1435 if (!pConnection
->dataQueue
.Full())
1437 SConnection::SData sdata
;
1439 sdata
.data
= MemAlloc(pPacket
->GetWriteBufferPos());
1441 if (sdata
.data
!= TMemInvalidHdl
)
1443 uint8
* pData
= (uint8
*)MemGetPtr(sdata
.data
);
1445 memcpy(pData
, pPacket
->GetWriteBuffer(), pPacket
->GetWriteBufferPos());
1447 sdata
.dataSize
= pPacket
->GetWriteBufferPos();
1448 sdata
.counter
= pConnection
->counterOut
;
1449 pConnection
->dataQueue
.Push(sdata
);
1451 pPacket
->SetWriteBufferPos(0);
1458 SECURE_NET_LOG("[Lobby] Trying to send to connection " PRFORMAT_LCINFO
" but the send queue is full", PRARG_LCINFO(connectionID
, pConnection
->addr
));
1459 const int numPacketsInQueue
= pConnection
->dataQueue
.Size();
1460 for (int i
= 0; i
< numPacketsInQueue
; ++i
)
1462 SConnection::SData
& data
= pConnection
->dataQueue
[i
];
1463 NetLog("counter %d size %d", data
.counter
, data
.dataSize
);
1464 LogPacketsInBuffer((uint8
*)MemGetPtr(data
.data
), data
.dataSize
);
1467 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1472 bool CCryLobby::AddPacketToReliableBuildPacket(CryLobbyConnectionID connectionID
, CCryLobbyPacket
* pPacket
)
1474 #if USE_LOBBY_REMOTE_CONNECTIONS
1475 SConnection
* pConnection
= &m_connection
[connectionID
];
1476 CCrySharedLobbyPacket
* pSBuildPacket
= (CCrySharedLobbyPacket
*)&pConnection
->reliableBuildPacket
;
1477 SCryLobbyPacketHeader
* pBuildPacketHeader
= pSBuildPacket
->GetLobbyPacketHeader();
1478 SCryLobbyPacketDataHeader
* pBuildDataHeader
= pSBuildPacket
->GetLobbyPacketDataHeader();
1479 CCrySharedLobbyPacket
* pSPacket
= (CCrySharedLobbyPacket
*)pPacket
;
1480 SCryLobbyPacketHeader
* pPacketHeader
= pSPacket
->GetLobbyPacketHeader();
1481 SCryLobbyPacketDataHeader
* pDataHeader
= pSPacket
->GetLobbyPacketDataHeader();
1482 uint8
* pDataBuffer
= pSPacket
->GetWriteBuffer() + CryLobbyPacketReliableHeaderSize
;
1483 uint32 dataSize
= pSPacket
->GetWriteBufferPos() - CryLobbyPacketReliableHeaderSize
;
1485 if (pSPacket
->GetWriteBufferPos() > MAX_LOBBY_PACKET_SIZE
)
1487 if (pSBuildPacket
->GetWriteBufferPos() > 0)
1489 if (!AddReliablePacketToSendQueue(connectionID
, pSBuildPacket
))
1495 pConnection
->counterOut
++;
1497 *pBuildPacketHeader
= *pPacketHeader
;
1498 *pBuildDataHeader
= *pDataHeader
;
1500 pPacketHeader
->counterOut
= pConnection
->counterOut
;
1501 pPacketHeader
->counterIn
= pConnection
->counterIn
;
1502 pDataHeader
->dataSize
= dataSize
;
1504 uint32 bufferPos
= pSPacket
->GetWriteBufferPos();
1505 pSPacket
->SetWriteBufferPos(0);
1506 pSPacket
->WritePacketHeader();
1507 pSPacket
->WriteDataHeader();
1508 pSPacket
->SetWriteBufferPos(bufferPos
);
1510 if (AddReliablePacketToSendQueue(connectionID
, pSPacket
))
1518 if (pSBuildPacket
->GetWriteBufferPos() > 0)
1520 // Send and start new if
1521 if (((pSBuildPacket
->GetWriteBufferPos() + CryLobbyPacketReliableDataHeaderSize
+ dataSize
) > pSBuildPacket
->GetReadBufferSize()) || // Data will not fit in current packet
1522 (pBuildPacketHeader
->fromUID
.m_sid
!= pPacketHeader
->fromUID
.m_sid
)) // sid has changed due to host migration
1524 if (!AddReliablePacketToSendQueue(connectionID
, pSBuildPacket
))
1531 if (pSBuildPacket
->GetWriteBufferPos() == 0)
1533 // Build packet is empty so start with this packet
1534 pConnection
->counterOut
++;
1536 *pBuildPacketHeader
= *pPacketHeader
;
1537 *pBuildDataHeader
= *pDataHeader
;
1539 pBuildPacketHeader
->counterOut
= pConnection
->counterOut
;
1540 pBuildPacketHeader
->counterIn
= pConnection
->counterIn
;
1541 pBuildDataHeader
->dataSize
= dataSize
;
1543 pSBuildPacket
->WritePacketHeader();
1544 pSBuildPacket
->WriteDataHeader();
1545 pSBuildPacket
->WriteData(pDataBuffer
, dataSize
);
1549 // Add data to end of current packet.
1550 *pBuildDataHeader
= *pDataHeader
;
1551 pBuildDataHeader
->dataSize
= dataSize
;
1552 pSBuildPacket
->WriteDataHeader();
1553 pSBuildPacket
->WriteData(pDataBuffer
, dataSize
);
1557 #else // USE_LOBBY_REMOTE_CONNECTIONS
1559 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1562 void CCryLobby::CalculatePacketTypeEncoding()
1564 CMTRand_int32
r(CRYLOBBY_PACKET_TYPE_ENCODE_SEED
);
1567 for (i
= 0; i
< 256; i
++)
1569 m_encodePacketType
[i
] = i
;
1572 for (i
= 0; i
< 1024; i
++)
1574 uint32 lhs
= r
.GenerateUint32() & 0xff;
1575 uint32 rhs
= r
.GenerateUint32() & 0xff;
1577 std::swap(m_encodePacketType
[lhs
], m_encodePacketType
[rhs
]);
1580 for (i
= 0; i
< 256; i
++)
1582 m_decodePacketType
[m_encodePacketType
[i
]] = i
;
1585 for (i
= m_servicePacketEnd
[eCLS_LAN
]; i
<= CRYLANLOBBY_PACKET_MAX
; i
++)
1587 m_decodePacketType
[m_encodePacketType
[i
]] = eLobbyPT_InvalidPackeType
;
1590 for (i
= m_servicePacketEnd
[eCLS_Online
]; i
<= CRYONLINELOBBY_PACKET_MAX
; i
++)
1592 m_decodePacketType
[m_encodePacketType
[i
]] = eLobbyPT_InvalidPackeType
;
1595 for (i
= m_userPacketEnd
; i
<= CRYLOBBY_USER_PACKET_MAX
; i
++)
1597 m_decodePacketType
[m_encodePacketType
[i
]] = eLobbyPT_InvalidPackeType
;
1601 void CCryLobby::EncodePacketDataHeader(CCryLobbyPacket
* pPacket
)
1603 CCrySharedLobbyPacket
* pSPacket
= (CCrySharedLobbyPacket
*)pPacket
;
1604 SCryLobbyPacketDataHeader
* pDataHeader
= pSPacket
->GetLobbyPacketDataHeader();
1606 pDataHeader
->lobbyPacketType
= m_encodePacketType
[pDataHeader
->lobbyPacketType
];
1609 void CCryLobby::DecodePacketDataHeader(CCryLobbyPacket
* pPacket
)
1611 CCrySharedLobbyPacket
* pSPacket
= (CCrySharedLobbyPacket
*)pPacket
;
1612 SCryLobbyPacketDataHeader
* pDataHeader
= pSPacket
->GetLobbyPacketDataHeader();
1614 pDataHeader
->lobbyPacketType
= m_decodePacketType
[pDataHeader
->lobbyPacketType
];
1617 ESocketError
CCryLobby::Send(CCryLobbyPacket
* pPacket
, const TNetAddress
& to
, CryLobbyConnectionID connectionID
, CryLobbySendID
* pSendID
)
1619 #if USE_LOBBY_REMOTE_CONNECTIONS
1620 CCrySharedLobbyPacket
* pSPacket
= (CCrySharedLobbyPacket
*)pPacket
;
1621 ESocketError ret
= eSE_Ok
;
1623 EncodePacketDataHeader(pSPacket
);
1625 if (pSPacket
->GetReliable())
1627 if (connectionID
== CryLobbyInvalidConnectionID
)
1629 connectionID
= FindConnection(to
);
1631 if (connectionID
== CryLobbyInvalidConnectionID
)
1633 connectionID
= CreateConnection(to
);
1637 if (connectionID
!= CryLobbyInvalidConnectionID
)
1639 SConnection
* pConnection
= &m_connection
[connectionID
];
1641 if ((pConnection
->state
== eCLCS_Connected
) || (pConnection
->state
== eCLCS_Pending
))
1643 if (AddPacketToReliableBuildPacket(connectionID
, pSPacket
))
1645 if (pConnection
->dataQueue
.Empty())
1647 AddReliablePacketToSendQueue(connectionID
, &pConnection
->reliableBuildPacket
);
1649 SConnection::SData
& data
= pConnection
->dataQueue
.Front();
1651 SECURE_NET_LOG("[lobby] Send reliable connection " PRFORMAT_LCINFO
" counter %d size %d", PRARG_LCINFO(connectionID
, pConnection
->addr
), data
.counter
, data
.dataSize
);
1653 LogPacketsInBuffer((uint8
*)MemGetPtr(data
.data
), data
.dataSize
);
1655 // Data hasn't been acknowledged so try sending again
1656 SSocketService
* pSocketService
= GetCorrectSocketServiceForAddr(pConnection
->addr
);
1657 if (pSocketService
->m_socket
)
1659 if (pSocketService
->m_socket
->Send(EncryptPacket((uint8
*)MemGetPtr(data
.data
), data
.dataSize
), data
.dataSize
, pConnection
->addr
) != eSE_Ok
)
1661 SECURE_NET_LOG("[Lobby] Failed to send setting connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(connectionID
, pConnection
->addr
));
1662 pConnection
->state
= eCLCS_NotConnected
;
1669 *pSendID
= CryLobbyCreateSendID(connectionID
, pConnection
->counterOut
);
1674 ret
= eSE_MiscFatalError
;
1680 ret
= eSE_MiscFatalError
;
1685 SSocketService
* pSocketService
= GetCorrectSocketServiceForAddr(to
);
1687 if (pSocketService
->m_socket
)
1689 uint8
* pBuffer
= pSPacket
->GetWriteBuffer();
1690 uint32 bufferSize
= pSPacket
->GetWriteBufferPos();
1692 pSPacket
->SetWriteBufferPos(0);
1693 pSPacket
->WritePacketHeader();
1694 pSPacket
->WriteDataHeader();
1695 pSPacket
->SetWriteBufferPos(bufferSize
);
1699 *pSendID
= CryLobbyInvalidSendID
;
1702 ret
= pSocketService
->m_socket
->Send(EncryptPacket(pBuffer
, bufferSize
), bufferSize
, to
);
1706 ret
= eSE_MiscFatalError
;
1710 DecodePacketDataHeader(pSPacket
);
1713 #else // USE_LOBBY_REMOTE_CONNECTIONS
1714 return eSE_MiscFatalError
;
1715 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1718 ESocketError
CCryLobby::SendVoice(CCryLobbyPacket
* pPacket
, const TNetAddress
& to
)
1720 #if USE_LOBBY_REMOTE_CONNECTIONS
1721 SSocketService
* pSocketService
= GetCorrectSocketService(m_service
);
1723 if (pSocketService
->m_socket
)
1725 CCrySharedLobbyPacket
* pSPacket
= (CCrySharedLobbyPacket
*)pPacket
;
1726 uint8
* pBuffer
= pSPacket
->GetWriteBuffer();
1727 uint32 bufferSize
= pSPacket
->GetWriteBufferPos();
1729 EncodePacketDataHeader(pSPacket
);
1731 pSPacket
->SetWriteBufferPos(0);
1732 pSPacket
->WritePacketHeader();
1733 pSPacket
->WriteDataHeader();
1734 pSPacket
->SetWriteBufferPos(bufferSize
);
1736 DecodePacketDataHeader(pSPacket
);
1738 return pSocketService
->m_socket
->SendVoice(EncryptPacket(pBuffer
, bufferSize
), bufferSize
, to
);
1740 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1742 return eSE_MiscFatalError
;
1745 void CCryLobby::UpdateConnectionPing(CryLobbyConnectionID connectionID
, CryPing ping
)
1747 #if USE_LOBBY_REMOTE_CONNECTIONS
1748 SConnection
* pConnection
= &m_connection
[connectionID
];
1750 pConnection
->ping
.times
[pConnection
->ping
.currentTime
] = ping
;
1751 pConnection
->ping
.currentTime
= (pConnection
->ping
.currentTime
+ 1) % NUM_LOBBY_PINGS
;
1753 uint32 numValidPings
= 0;
1754 CryPingAccumulator totalTime
= 0;
1756 for (uint32 i
= 0; i
< NUM_LOBBY_PINGS
; ++i
)
1758 if (pConnection
->ping
.times
[i
] != CRYLOBBY_INVALID_PING
)
1760 totalTime
+= pConnection
->ping
.times
[i
];
1767 pConnection
->ping
.aveTime
= (CryPing
)(totalTime
/ numValidPings
);
1771 pConnection
->ping
.aveTime
= CRYLOBBY_INVALID_PING
;
1773 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1776 CryPing
CCryLobby::GetConnectionPing(CryLobbyConnectionID connectionID
)
1778 #if USE_LOBBY_REMOTE_CONNECTIONS
1779 if ((connectionID
!= CryLobbyInvalidConnectionID
) && (connectionID
< MAX_LOBBY_CONNECTIONS
))
1781 return m_connection
[connectionID
].ping
.aveTime
;
1783 #endif // USE_LOBBY_REMOTE_CONNECTIONS
1785 return CRYLOBBY_INVALID_PING
;
1788 bool CCryLobby::GetNextPacketFromBuffer(const uint8
* pData
, uint32 dataSize
, uint32
& dataPos
, CCryLobbyPacket
* pPacket
)
1790 CCrySharedLobbyPacket
* pSPacket
= (CCrySharedLobbyPacket
*)pPacket
;
1794 pSPacket
->SetReadBuffer(pData
, dataSize
);
1795 pSPacket
->SetReadBufferPos(0);
1796 pSPacket
->ReadPacketHeader();
1797 dataPos
= CryLobbyPacketReliablePacketHeaderSize
;
1800 if (dataPos
< dataSize
)
1802 SCryLobbyPacketDataHeader
* pDataHeader
= pSPacket
->GetLobbyPacketDataHeader();
1804 pSPacket
->SetReadBuffer(pData
+ dataPos
- CryLobbyPacketReliablePacketHeaderSize
, dataSize
- (dataPos
- CryLobbyPacketReliablePacketHeaderSize
));
1805 pSPacket
->SetReadBufferPos(CryLobbyPacketReliablePacketHeaderSize
);
1806 pSPacket
->ReadDataHeader();
1807 pSPacket
->SetReadBuffer(pData
+ dataPos
- CryLobbyPacketReliablePacketHeaderSize
, pDataHeader
->dataSize
+ CryLobbyPacketReliableHeaderSize
);
1808 pSPacket
->SetReadBufferPos(CryLobbyPacketReliableHeaderSize
+ pDataHeader
->dataSize
);
1809 dataPos
+= CryLobbyPacketReliableDataHeaderSize
+ pDataHeader
->dataSize
;
1816 void CCryLobby::ProcessPacket(const TNetAddress
& addr
, CryLobbyConnectionID connectionID
, CCryLobbyPacket
* pPacket
)
1818 #if USE_LOBBY_REMOTE_CONNECTIONS
1819 SConnection
* pConnection
= (connectionID
!= CryLobbyInvalidConnectionID
) ? &m_connection
[connectionID
] : NULL
;
1821 switch (pPacket
->StartRead())
1826 uint8 counterIn
= pPacket
->ReadUINT8();
1828 if (!pConnection
->dataQueue
.Empty())
1830 SConnection::SData
& qdata
= pConnection
->dataQueue
.Front();
1832 if (counterIn
== qdata
.counter
)
1834 #if !defined(NO_NETWORK_SECURITY_LOGS)
1835 const uint8 qDataCounter
= qdata
.counter
;
1837 // Other end has received the packet we are trying to send
1838 OnSendComplete(addr
);
1839 SECURE_NET_LOG("[lobby] Got ack on connection " PRFORMAT_LCINFO
" counterIn=%u, qDataCounter=%u", PRARG_LCINFO(connectionID
, pConnection
->addr
), counterIn
, qDataCounter
);
1846 case eLobbyPT_ConnectionRequest
:
1848 #if RESET_CONNECTED_CONNECTION
1849 uint64 cookie
= pPacket
->ReadUINT64();
1852 if (connectionID
== CryLobbyInvalidConnectionID
)
1854 connectionID
= CreateConnection(addr
);
1858 pConnection
= &m_connection
[connectionID
];
1860 if (pConnection
->state
== eCLCS_Freeing
)
1862 SECURE_NET_LOG("[Lobby] Connection Request on existing Freeing connection " PRFORMAT_LCINFO
, PRARG_LCINFO(connectionID
, pConnection
->addr
));
1863 uint8 refCount
= pConnection
->refCount
;
1864 FreeConnection(connectionID
);
1865 connectionID
= CreateConnection(addr
);
1866 NetLog("[Lobby] setting refCount back to %u for resetted connection", refCount
);
1867 pConnection
= &m_connection
[connectionID
];
1868 pConnection
->refCount
= refCount
;
1870 #if RESET_CONNECTED_CONNECTION
1873 if ((pConnection
->recvCookie
!= cookie
) && (pConnection
->recvCookie
!= INVALID_CONNECTION_COOKIE
))
1875 SECURE_NET_LOG("[Lobby] Connection Request on existing connected connection, current cookie %llx new cookie %llx Freeing connection " PRFORMAT_LCINFO
, pConnection
->recvCookie
, cookie
, PRARG_LCINFO(connectionID
, pConnection
->addr
));
1876 CCryMatchMaking
* pMatchMaking
= (CCryMatchMaking
*)GetMatchMaking();
1879 pMatchMaking
->ResetConnection(connectionID
);
1882 uint8 refCount
= pConnection
->refCount
;
1884 FreeConnection(connectionID
);
1885 connectionID
= CreateConnection(addr
);
1887 if (connectionID
!= CryLobbyInvalidConnectionID
)
1889 NetLog("[Lobby] setting refCount back to %u for resetted connection", refCount
);
1891 pConnection
= &m_connection
[connectionID
];
1892 pConnection
->refCount
= refCount
;
1899 if (connectionID
!= CryLobbyInvalidConnectionID
)
1901 pConnection
= &m_connection
[connectionID
];
1903 const uint32 MaxBufferSize
= CryLobbyPacketHeaderSize
1904 #if RESET_CONNECTED_CONNECTION
1905 + CryLobbyPacketUINT64Size
;
1906 #endif // RESET_CONNECTED_CONNECTION
1908 uint8 buffer
[MaxBufferSize
];
1909 CCrySharedLobbyPacket resultPacket
;
1911 #if RESET_CONNECTED_CONNECTION
1912 pConnection
->recvCookie
= cookie
;
1915 pConnection
->state
= eCLCS_Connected
;
1917 resultPacket
.SetWriteBuffer(buffer
, MaxBufferSize
);
1918 resultPacket
.StartWrite(eLobbyPT_ConnectionRequestResult
, false);
1919 #if RESET_CONNECTED_CONNECTION
1920 SECURE_NET_LOG("[Lobby] Sending cookie %llx with connection " PRFORMAT_LCINFO
, pConnection
->sendCookie
, PRARG_LCINFO(connectionID
, pConnection
->addr
));
1921 resultPacket
.WriteUINT64(pConnection
->sendCookie
);
1924 if (Send(&resultPacket
, pConnection
->addr
, connectionID
, NULL
) != eSE_Ok
)
1926 SECURE_NET_LOG("[Lobby] Failed to send setting connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(connectionID
, pConnection
->addr
));
1927 pConnection
->state
= eCLCS_NotConnected
;
1934 case eLobbyPT_ConnectionRequestResult
:
1937 pConnection
->state
= eCLCS_Connected
;
1938 #if RESET_CONNECTED_CONNECTION
1939 pConnection
->recvCookie
= pPacket
->ReadUINT64();
1940 SECURE_NET_LOG("[Lobby] Setting recvCookie %llx for connection " PRFORMAT_LCINFO
, pConnection
->recvCookie
, PRARG_LCINFO(connectionID
, pConnection
->addr
));
1949 CTimeValue currentTime
= gEnv
->pTimer
->GetAsyncTime();
1950 CTimeValue recvTime
= pPacket
->GetRecvTime();
1951 uint64 timeDelayed
= (currentTime
- recvTime
).GetMilliSecondsAsInt64();
1952 const uint32 MaxBufferSize
= CryLobbyPacketHeaderSize
+ CryLobbyPacketUINT64Size
;
1953 uint8 buffer
[MaxBufferSize
];
1954 CCrySharedLobbyPacket pongPacket
;
1956 pongPacket
.SetWriteBuffer(buffer
, MaxBufferSize
);
1957 uint64 time
= pPacket
->ReadUINT64() + timeDelayed
;
1959 pongPacket
.StartWrite(eLobbyPT_Pong
, false);
1960 pongPacket
.WriteUINT64(time
);
1962 if (Send(&pongPacket
, pConnection
->addr
, connectionID
, NULL
) != eSE_Ok
)
1964 SECURE_NET_LOG("[Lobby] Failed to send setting connection " PRFORMAT_LCINFO
" to eCLCS_NotConnected", PRARG_LCINFO(connectionID
, pConnection
->addr
));
1965 pConnection
->state
= eCLCS_NotConnected
;
1974 CTimeValue recvTime
= pPacket
->GetRecvTime();
1975 uint64 sendTime
= pPacket
->ReadUINT64();
1976 uint64 pingTime
= recvTime
.GetMilliSecondsAsInt64() - sendTime
;
1977 if (pingTime
> CRYLOBBY_INVALID_PING
)
1979 pingTime
= CRYLOBBY_INVALID_PING
;
1982 UpdateConnectionPing(connectionID
, (CryPing
)pingTime
);
1987 case eLobbyPT_InvalidPackeType
:
1990 pConnection
->state
= eCLCS_NotConnected
;
1996 if (m_services
[m_service
])
1998 // Give packet to the current service
1999 m_services
[m_service
]->OnPacket(addr
, pPacket
);
2004 #endif // USE_LOBBY_REMOTE_CONNECTIONS
2007 void CCryLobby::OnPacket(const TNetAddress
& addr
, const uint8
* pData
, uint32 length
)
2009 #if USE_LOBBY_REMOTE_CONNECTIONS
2010 CryLobbyConnectionID connectionID
= FindConnection(addr
);
2011 SConnection
* pConnection
= (connectionID
!= CryLobbyInvalidConnectionID
) ? &m_connection
[connectionID
] : NULL
;
2013 if (pData
[0] == GetLobbyPacketID())
2015 m_cachedPacketBuffer
.WritePacket(addr
, pData
, length
);
2020 pConnection
->timeSinceRecv
= 0;
2022 #endif // USE_LOBBY_REMOTE_CONNECTIONS
2025 void CCryLobby::ProcessCachedPacketBuffer(void)
2027 #if USE_LOBBY_REMOTE_CONNECTIONS
2028 while (m_cachedPacketBuffer
.PacketsAvailable())
2030 CTimeValue recvTime
;
2034 m_cachedPacketBuffer
.ReadPacket(recvTime
, addr
, pData
, length
);
2036 CryLobbyConnectionID connectionID
= FindConnection(addr
);
2037 SConnection
* pConnection
= (connectionID
!= CryLobbyInvalidConnectionID
) ? &m_connection
[connectionID
] : NULL
;
2039 const uint8
* pDecodedData
;
2040 CCrySharedLobbyPacket packet
;
2041 SCryLobbyPacketHeader
* pPacketHeader
= packet
.GetLobbyPacketHeader();
2042 SCryLobbyPacketDataHeader
* pDataHeader
= packet
.GetLobbyPacketDataHeader();
2043 bool processPacket
= true;
2045 pDecodedData
= DecryptPacket(pData
, length
);
2047 packet
.SetReadBuffer(pDecodedData
, length
);
2048 packet
.SetReadBufferPos(0);
2049 packet
.ReadPacketHeader();
2050 pPacketHeader
->recvTime
= recvTime
;
2052 if (packet
.GetReliable())
2054 if (pConnection
&& ((pConnection
->state
== eCLCS_Pending
) || (pConnection
->state
== eCLCS_Connected
)))
2056 SECURE_NET_LOG("[lobby] OnPacket reliable connection " PRFORMAT_LCINFO
" size %u", PRARG_LCINFO(connectionID
, pConnection
->addr
), length
);
2058 if (((uint8
)(pConnection
->counterIn
- pPacketHeader
->counterOut
)) == CONNECTION_COUNTER_MAX
)
2060 // This is a new packet
2061 NetLog("[lobby] New packet counter %d", pPacketHeader
->counterOut
);
2063 pConnection
->counterIn
= pPacketHeader
->counterOut
;
2065 if (!pConnection
->dataQueue
.Empty())
2067 SConnection::SData
& qdata
= pConnection
->dataQueue
.Front();
2069 if (pPacketHeader
->counterIn
== qdata
.counter
)
2071 #if !defined(NO_NETWORK_SECURITY_LOGS)
2072 const uint8 qDataCounter
= qdata
.counter
;
2074 // Other end has received the packet we are trying to send
2075 OnSendComplete(addr
);
2076 SECURE_NET_LOG("[lobby] Got ack(first) on connection " PRFORMAT_LCINFO
" counterIn=%u, qDataCounter=%u", PRARG_LCINFO(connectionID
, pConnection
->addr
), pPacketHeader
->counterIn
, qDataCounter
);
2082 processPacket
= false;
2083 NetLog("[lobby] Repeat packet counter %d", pPacketHeader
->counterOut
);
2086 const uint32 MaxBufferSize
= CryLobbyPacketUnReliableHeaderSize
+ CryLobbyPacketUINT8Size
;
2087 uint8 buffer
[MaxBufferSize
];
2088 CCryLobbyPacket ackPacket
;
2090 ackPacket
.SetWriteBuffer(buffer
, MaxBufferSize
);
2091 ackPacket
.StartWrite(eLobbyPT_Ack
, false);
2092 ackPacket
.WriteUINT8(pPacketHeader
->counterOut
);
2094 Send(&ackPacket
, addr
, connectionID
, NULL
);
2096 NetLog("[lobby] Send ack (counter=%u)", pPacketHeader
->counterOut
);
2100 NetLog("[lobby] OnPacket reliable packet for non connected connection " PRFORMAT_LCINFO
" size %u ignoring", PRARG_LCINFO(connectionID
, addr
), length
);
2102 processPacket
= false;
2104 // We don't have a valid connection for this reliable packet.
2105 // This will most likely happen if we have disconnected but the other end doesn't know and is trying to disconnect from us.
2106 // If this is one of the packet types that is kept and still sent after a disconnect send back an ack to stop the other end sending.
2108 bool sendAck
= false;
2110 while (GetNextPacketFromBuffer(pDecodedData
, length
, dataPos
, &packet
))
2112 #if !defined(EXCLUDE_NORMAL_LOG)
2113 uint32 encodedPacketType
= pDataHeader
->lobbyPacketType
;
2115 DecodePacketDataHeader(&packet
);
2117 if (KeepPacketAfterDisconnect(pDataHeader
->lobbyPacketType
))
2120 NetLog(" Ignoring packet %u (%u) size %u Still needs ack", pDataHeader
->lobbyPacketType
, encodedPacketType
, pDataHeader
->dataSize
);
2124 NetLog(" Ignoring packet %u (%u) size %u Doesn't need ack", pDataHeader
->lobbyPacketType
, encodedPacketType
, pDataHeader
->dataSize
);
2130 const uint32 MaxBufferSize
= CryLobbyPacketUnReliableHeaderSize
+ CryLobbyPacketUINT8Size
;
2131 uint8 buffer
[MaxBufferSize
];
2132 CCryLobbyPacket ackPacket
;
2134 ackPacket
.SetWriteBuffer(buffer
, MaxBufferSize
);
2135 ackPacket
.StartWrite(eLobbyPT_Ack
, false);
2136 ackPacket
.WriteUINT8(pPacketHeader
->counterOut
);
2138 Send(&ackPacket
, addr
, connectionID
, NULL
);
2140 NetLog("[lobby] Send ack for non connected connection (counter=%u)", pPacketHeader
->counterOut
);
2147 if (packet
.GetReliable())
2151 while (GetNextPacketFromBuffer(pDecodedData
, length
, dataPos
, &packet
))
2153 #if !defined(EXCLUDE_NORMAL_LOG)
2154 uint32 encodedPacketType
= pDataHeader
->lobbyPacketType
;
2156 DecodePacketDataHeader(&packet
);
2157 NetLog(" Process packet %d (%d) size %d", pDataHeader
->lobbyPacketType
, encodedPacketType
, pDataHeader
->dataSize
);
2158 ProcessPacket(addr
, connectionID
, &packet
);
2163 packet
.ReadDataHeader();
2164 DecodePacketDataHeader(&packet
);
2165 ProcessPacket(addr
, connectionID
, &packet
);
2170 m_cachedPacketBuffer
.Reset();
2171 #endif // USE_LOBBY_REMOTE_CONNECTIONS
2174 void CCryLobby::OnError(const TNetAddress
& addr
, ESocketError error
)
2176 #if USE_LOBBY_REMOTE_CONNECTIONS
2177 CryLobbyConnectionID c
;
2178 CryLobbySendID sendID
= CryLobbyInvalidSendID
;
2180 if (ConnectionFromAddress(&c
, addr
))
2182 SConnection
* connection
= &m_connection
[c
];
2184 while (!connection
->dataQueue
.Empty())
2186 SConnection::SData
& data
= connection
->dataQueue
.Front();
2188 sendID
= CryLobbyCreateSendID(c
, data
.counter
);
2192 if (m_services
[m_service
])
2194 m_services
[m_service
]->OnError(addr
, error
, sendID
);
2197 SECURE_NET_LOG("[lobby] Socket error %d on connection " PRFORMAT_LCINFO
" free send data counter %u", error
, PRARG_LCINFO(c
, connection
->addr
), data
.counter
);
2199 connection
->dataQueue
.Pop();
2202 connection
->state
= eCLCS_NotConnected
;
2206 if (m_services
[m_service
])
2208 m_services
[m_service
]->OnError(addr
, error
, sendID
);
2211 #endif // USE_LOBBY_REMOTE_CONNECTIONS
2214 void CCryLobby::OnSendComplete(const TNetAddress
& addr
)
2216 #if USE_LOBBY_REMOTE_CONNECTIONS
2217 CryLobbyConnectionID c
;
2218 CryLobbySendID sendID
= CryLobbyInvalidSendID
;
2220 if (ConnectionFromAddress(&c
, addr
))
2222 SConnection
* connection
= &m_connection
[c
];
2224 if (!connection
->dataQueue
.Empty())
2226 SConnection::SData
& data
= connection
->dataQueue
.Front();
2228 sendID
= CryLobbyCreateSendID(c
, data
.counter
);
2230 SECURE_NET_LOG("[lobby] Send complete on connection " PRFORMAT_LCINFO
" free send data counter %d", PRARG_LCINFO(c
, connection
->addr
), data
.counter
);
2231 LogPacketsInBuffer((uint8
*)MemGetPtr(data
.data
), data
.dataSize
);
2235 connection
->dataQueue
.Pop();
2239 if (m_services
[m_service
])
2241 m_services
[m_service
]->OnSendComplete(addr
, sendID
);
2243 #endif // USE_LOBBY_REMOTE_CONNECTIONS
2246 #if NETWORK_HOST_MIGRATION
2247 uint8
CCryLobby::GetActiveConnections(void)
2251 for (uint32 index
= 0; index
< MAX_LOBBY_CONNECTIONS
; ++index
)
2253 if (m_connection
[index
].used
&& (m_connection
[index
].state
== eCLCS_Connected
))
2263 void CCryLobby::RegisterEventInterest(ECryLobbySystemEvent eventOfInterest
, CryLobbyEventCallback cb
, void* pUserData
)
2265 SEventCBData newEvent
;
2268 newEvent
.pUserData
= pUserData
;
2269 newEvent
.event
= eventOfInterest
;
2271 m_callbacks
.push_back(newEvent
);
2274 void CCryLobby::UnregisterEventInterest(ECryLobbySystemEvent eventOfInterest
, CryLobbyEventCallback cb
, void* pUserData
)
2276 SEventCBData newEvent
;
2279 newEvent
.pUserData
= pUserData
;
2280 newEvent
.event
= eventOfInterest
;
2282 stl::find_and_erase(m_callbacks
, newEvent
);
2285 void CCryLobby::DispatchEvent(ECryLobbySystemEvent evnt
, UCryLobbyEventData data
)
2287 EventCBList::iterator callbackItem
;
2289 for (callbackItem
= m_callbacks
.begin(); callbackItem
!= m_callbacks
.end(); ++callbackItem
)
2291 if (callbackItem
->event
== evnt
)
2293 callbackItem
->cb(data
, callbackItem
->pUserData
);
2298 void CCryLobby::GetConfigurationInformation(SConfigurationParams
* infos
, uint32 infoCnt
)
2302 m_configCB(GetLobbyServiceType(), infos
, infoCnt
);
2306 ICryTCPServicePtr
CCryLobbyService::GetTCPService(const char* pService
)
2308 #if USE_CRY_TCPSERVICE
2309 if (m_pTCPServiceFactory
)
2311 return m_pTCPServiceFactory
->GetTCPService(pService
);
2313 #endif // USE_CRY_TCPSERVICE
2317 ICryTCPServicePtr
CCryLobbyService::GetTCPService(const char* pServer
, uint16 port
, const char* pUrlPrefix
)
2319 #if USE_CRY_TCPSERVICE
2320 if (m_pTCPServiceFactory
)
2322 return m_pTCPServiceFactory
->GetTCPService(pServer
, port
, pUrlPrefix
);
2324 #endif // USE_CRY_TCPSERVICE
2328 bool CCryLobbyService::GetFlag(ECryLobbyServiceFlag flag
)
2330 return (m_lobbyServiceFlags
& flag
) == flag
;
2334 // Is the given flag true for the lobby service of the given type?
2336 // service - lobby service to be queried
2337 // flag - flag to be queried
2339 // True if the flag is true.
2340 bool CCryLobby::GetLobbyServiceFlag(ECryLobbyService service
, ECryLobbyServiceFlag flag
)
2342 bool result
= false;
2344 if (m_services
[service
])
2346 result
= m_services
[service
]->GetFlag(flag
);
2352 CCryLobbyService::CCryLobbyService(CCryLobby
* pLobby
, ECryLobbyService service
)
2354 , m_service(service
)
2355 #if USE_CRY_TCPSERVICE
2356 , m_pTCPServiceFactory(NULL
)
2357 #endif // USE_CRY_TCPSERVICE
2359 m_lobbyServiceFlags
= eCLSF_AllowMultipleSessions
| eCLSF_SupportHostMigration
;
2360 ZeroMemory(&m_tasks
, sizeof(m_tasks
));
2363 CCryLobbyService::~CCryLobbyService()
2368 ECryLobbyError
CCryLobbyService::Initialise(ECryLobbyServiceFeatures features
, CryLobbyServiceCallback pCB
)
2370 if (features
& eCLSO_Base
)
2374 for (uint32 i
= 0; i
< MAX_LOBBY_TASKS
; i
++)
2376 m_tasks
[i
].used
= false;
2380 return eCLE_Success
;
2383 ECryLobbyError
CCryLobbyService::Terminate(ECryLobbyServiceFeatures features
, CryLobbyServiceCallback pCB
)
2385 if (features
& eCLSO_Base
)
2389 FROM_GAME_TO_LOBBY(&CCryLobbyService::FreeSocketNT
, this);
2392 return eCLE_Success
;
2395 void CCryLobbyService::CreateSocketNT(void)
2397 m_pLobby
->InternalSocketCreate(m_service
);
2400 void CCryLobbyService::FreeSocketNT(void)
2402 m_pLobby
->InternalSocketFree(m_service
);
2405 ECryLobbyError
CCryLobbyService::StartTask(uint32 eTask
, uint32 user
, bool startRunning
, CryLobbyServiceTaskID
* pLSTaskID
, CryLobbyTaskID
* pLTaskID
, void* pCb
, void* pCbArg
)
2407 CryLobbyTaskID lobbyTaskID
= m_pLobby
->CreateTask();
2409 if (lobbyTaskID
!= CryLobbyInvalidTaskID
)
2411 for (uint32 i
= 0; i
< MAX_LOBBY_TASKS
; i
++)
2413 STask
* pTask
= GetTask(i
);
2418 pTask
->lTaskID
= lobbyTaskID
;
2419 pTask
->error
= eCLE_Success
;
2420 pTask
->startedTask
= eTask
;
2422 pTask
->pCBArg
= pCbArg
;
2424 pTask
->running
= startRunning
;
2433 *pLTaskID
= lobbyTaskID
;
2436 for (uint32 j
= 0; j
< MAX_LOBBY_TASK_DATAS
; j
++)
2438 pTask
->dataMem
[j
] = TMemInvalidHdl
;
2439 pTask
->dataNum
[j
] = 0;
2442 return eCLE_Success
;
2446 m_pLobby
->ReleaseTask(lobbyTaskID
);
2449 return eCLE_TooManyTasks
;
2452 void CCryLobbyService::FreeTask(CryLobbyServiceTaskID lsTaskID
)
2454 STask
* pTask
= GetTask(lsTaskID
);
2456 m_pLobby
->ReleaseTask(pTask
->lTaskID
);
2458 for (uint32 i
= 0; i
< MAX_LOBBY_TASK_DATAS
; i
++)
2460 if (pTask
->dataMem
[i
] != TMemInvalidHdl
)
2462 m_pLobby
->MemFree(pTask
->dataMem
[i
]);
2463 pTask
->dataMem
[i
] = TMemInvalidHdl
;
2467 pTask
->used
= false;
2470 void CCryLobbyService::CancelTask(CryLobbyTaskID lTaskID
)
2474 CryLogAlways("[Lobby]Try cancel task %u", lTaskID
);
2476 if (lTaskID
!= CryLobbyInvalidTaskID
)
2478 for (uint32 i
= 0; i
< MAX_LOBBY_TASKS
; i
++)
2480 STask
* pTask
= GetTask(i
);
2482 CRY_ASSERT(pTask
, "CCryLobby: Task base pointers not setup");
2484 if (pTask
->used
&& (pTask
->lTaskID
== lTaskID
))
2486 CryLogAlways("[Lobby] Task %u canceled", lTaskID
);
2494 void CCryLobbyService::UpdateTaskError(CryLobbyServiceTaskID lsTaskID
, ECryLobbyError error
)
2496 STask
* pTask
= GetTask(lsTaskID
);
2498 if (pTask
->error
== eCLE_Success
)
2500 pTask
->error
= error
;
2504 void CCryLobbyService::StartTaskRunning(CryLobbyServiceTaskID lsTaskID
)
2508 STask
* pTask
= GetTask(lsTaskID
);
2512 pTask
->running
= true;
2514 switch (pTask
->startedTask
)
2516 case eT_GetUserPrivileges
:
2517 StopTaskRunning(lsTaskID
);
2523 void CCryLobbyService::StopTaskRunning(CryLobbyServiceTaskID lsTaskID
)
2525 STask
* pTask
= GetTask(lsTaskID
);
2529 pTask
->running
= false;
2531 TO_GAME_FROM_LOBBY(&CCryLobbyService::EndTask
, this, lsTaskID
);
2535 void CCryLobbyService::EndTask(CryLobbyServiceTaskID lsTaskID
)
2539 STask
* pTask
= GetTask(lsTaskID
);
2545 switch (pTask
->startedTask
)
2547 case eT_GetUserPrivileges
:
2548 if (!m_pLobby
->GetInternalSocket(m_service
))
2550 UpdateTaskError(lsTaskID
, eCLE_InternalError
);
2553 ((CryLobbyPrivilegeCallback
)pTask
->pCB
)(pTask
->lTaskID
, pTask
->error
, 0, pTask
->pCBArg
);
2558 if (pTask
->error
!= eCLE_Success
)
2560 NetLog("[Lobby] Lobby Service EndTask %u Result %d", pTask
->startedTask
, pTask
->error
);
2567 ECryLobbyError
CCryLobbyService::GetUserPrivileges(uint32 user
, CryLobbyTaskID
* pTaskID
, CryLobbyPrivilegeCallback pCB
, void* pCBArg
)
2569 ECryLobbyError error
;
2570 CryLobbyServiceTaskID tid
;
2574 error
= StartTask(eT_GetUserPrivileges
, user
, false, &tid
, pTaskID
, (void*)pCB
, pCBArg
);
2576 if (error
== eCLE_Success
)
2578 FROM_GAME_TO_LOBBY(&CCryLobbyService::StartTaskRunning
, this, tid
);
2584 void CCryLobbyService::GetSocketPorts(uint16
& connectPort
, uint16
& listenPort
)
2586 listenPort
= CLobbyCVars::Get().lobbyDefaultPort
;
2587 connectPort
= CLobbyCVars::Get().lobbyDefaultPort
;
2590 void CCryLobbyService::MakeAddrPCCompatible(TNetAddress
& addr
)
2594 void CCryLobby::MakeAddrPCCompatible(TNetAddress
& addr
)
2596 m_services
[m_service
]->MakeAddrPCCompatible(addr
);
2599 void CCryLobby::MakeConnectionPCCompatible(CryLobbyConnectionID connectionID
)
2601 if (connectionID
!= CryLobbyInvalidConnectionID
)
2603 m_services
[m_service
]->MakeAddrPCCompatible(m_connection
[connectionID
].addr
);
2607 CCryLobby::SSocketService
* CCryLobby::GetCorrectSocketServiceForAddr(const TNetAddress
& addr
)
2609 return &m_socketServices
[GetCorrectSocketServiceTypeForAddr(addr
)];
2612 ECryLobbyService
CCryLobby::GetCorrectSocketServiceTypeForAddr(const TNetAddress
& addr
)
2614 const SIPv4Addr
* pIPv4Addr
= stl::get_if
<SIPv4Addr
>(&addr
);
2616 if (pIPv4Addr
&& (pIPv4Addr
->lobbyService
!= eCLS_NumServices
))
2618 return ECryLobbyService(pIPv4Addr
->lobbyService
);
2624 CCryLobby::SSocketService
* CCryLobby::GetCorrectSocketService(ECryLobbyService serviceType
)
2626 //Note that there will always be a 2 sockets no matter which services are initialised
2627 return &m_socketServices
[serviceType
];
2630 uint16
CCryLobby::GetInternalSocketPort(ECryLobbyService service
)
2632 SSocketService
* pSocketService
= GetCorrectSocketService(service
);
2634 return pSocketService
->m_socketListenPort
;
2637 IDatagramSocketPtr
CCryLobby::GetInternalSocket(ECryLobbyService service
)
2639 SSocketService
* pSocketService
= GetCorrectSocketService(service
);
2641 return pSocketService
->m_socket
;
2644 const SCryLobbyParameters
& CCryLobby::GetLobbyParameters() const
2646 return m_serviceParams
[m_service
];
2649 uint32
CCryLobby::TimeSincePacketInMS(CryLobbyConnectionID c
) const
2651 #if USE_LOBBY_REMOTE_CONNECTIONS
2652 if (c
!= CryLobbyInvalidConnectionID
)
2654 if (m_connection
[c
].used
)
2656 return m_connection
[c
].timeSinceRecv
;
2659 #endif // USE_LOBBY_REMOTE_CONNECTIONS
2664 void CCryLobby::ForceTimeoutConnection(CryLobbyConnectionID c
)
2666 #if USE_LOBBY_REMOTE_CONNECTIONS
2667 if (c
!= CryLobbyInvalidConnectionID
)
2669 if (m_connection
[c
].used
)
2671 m_connection
[c
].timeSinceRecv
= LOBBY_FORCE_DISCONNECT_TIMER
;
2674 #endif // USE_LOBBY_REMOTE_CONNECTIONS
2677 const TNetAddress
* CCryLobby::GetNetAddress(CryLobbyConnectionID c
) const
2679 const TNetAddress
* pAddress
= NULL
;
2681 if ((c
!= CryLobbyInvalidConnectionID
) && (c
< MAX_LOBBY_CONNECTIONS
))
2683 if (m_connection
[c
].used
)
2685 pAddress
= &(m_connection
[c
].addr
);
2692 ECryLobbyError
CCryLobbyService::CreateTaskParamMem(CryLobbyServiceTaskID lsTaskID
, uint32 param
, const void* pParamData
, size_t paramDataSize
)
2694 STask
* pTask
= &m_tasks
[lsTaskID
];
2696 CRY_ASSERT(pTask
, "CCryLobbyService: Task base pointers not setup");
2698 if (paramDataSize
> 0)
2700 pTask
->dataMem
[param
] = m_pLobby
->MemAlloc(paramDataSize
);
2701 void* p
= m_pLobby
->MemGetPtr(pTask
->dataMem
[param
]);
2707 memcpy(p
, pParamData
, paramDataSize
);
2712 return eCLE_OutOfMemory
;
2716 return eCLE_Success
;
2719 const uint8
* CCryLobby::EncryptPacket(const uint8
* buffer
, uint32 length
)
2721 #if ENCRYPT_LOBBY_PACKETS
2724 m_tempEncryptionBuffer
[0] = buffer
[0];
2726 gEnv
->pNetwork
->EncryptBuffer(m_cipher
, m_tempEncryptionBuffer
+ 1, buffer
+ 1, length
- 1);
2728 return m_tempEncryptionBuffer
;
2737 const uint8
* CCryLobby::DecryptPacket(const uint8
* buffer
, uint32 length
)
2739 #if ENCRYPT_LOBBY_PACKETS
2742 m_tempDecryptionBuffer
[0] = buffer
[0];
2744 gEnv
->pNetwork
->DecryptBuffer(m_cipher
, m_tempDecryptionBuffer
+ 1, buffer
+ 1, length
- 1);
2746 return m_tempDecryptionBuffer
;
2755 bool CCryLobby::DecodeAddress(const TNetAddress
& address
, uint32
* pIP
, uint16
* pPort
)
2757 bool decoded
= true;
2759 const SIPv4Addr
* pIPv4Addr
= stl::get_if
<SIPv4Addr
>(&address
);
2760 if (pIPv4Addr
!= NULL
)
2762 *pIP
= pIPv4Addr
->addr
;
2763 *pPort
= pIPv4Addr
->port
;
2767 const TLocalNetAddress
* pLocalAddr
= stl::get_if
<TLocalNetAddress
>(&address
);
2768 if (pLocalAddr
!= NULL
)
2770 *pIP
= LOOPBACK_ADDRESS
;
2771 *pPort
= *pLocalAddr
;
2783 void CCryLobby::DecodeAddress(uint32 ip
, uint16 port
, char* ipstring
, bool ignorePort
)
2787 sprintf(ipstring
, "%u.%u.%u.%u", ((ip
>> 24) & 0xff), ((ip
>> 16) & 0xff), ((ip
>> 8) & 0xff), (ip
& 0xff));
2791 sprintf(ipstring
, "%u.%u.%u.%u:%u", ((ip
>> 24) & 0xff), ((ip
>> 16) & 0xff), ((ip
>> 8) & 0xff), (ip
& 0xff), port
);
2795 void CCryLobby::DecodeAddress(const TNetAddress
& address
, char* ipstring
, bool ignorePort
)
2800 if (DecodeAddress(address
, &ip
, &port
))
2802 DecodeAddress(ip
, port
, ipstring
, ignorePort
);
2806 sprintf(ipstring
, "<UNKNOWN>");
2810 bool CCryLobby::ConvertAddr(const TNetAddress
& addrIn
, CRYSOCKADDR_IN
* pSockAddr
)
2814 return ((INetworkPrivate
*)gEnv
->pNetwork
)->ConvertAddr(addrIn
, pSockAddr
);
2820 bool CCryLobby::ConvertAddr(const TNetAddress
& addrIn
, CRYSOCKADDR
* pSockAddr
, int* addrLen
)
2824 return ((INetworkPrivate
*)gEnv
->pNetwork
)->ConvertAddr(addrIn
, pSockAddr
, addrLen
);
2830 ISocketIOManager
* CCryLobby::GetExternalSocketIOManager()
2834 return &((INetworkPrivate
*)gEnv
->pNetwork
)->GetExternalSocketIOManager();
2840 ISocketIOManager
* CCryLobby::GetInternalSocketIOManager()
2844 return &((INetworkPrivate
*)gEnv
->pNetwork
)->GetInternalSocketIOManager();
2850 CNetAddressResolver
* CCryLobby::GetResolver()
2854 return ((INetworkPrivate
*)gEnv
->pNetwork
)->GetResolver();
2860 const CNetCVars
* CCryLobby::GetNetCVars()
2864 return &((INetworkPrivate
*)gEnv
->pNetwork
)->GetCVars();
2870 uint8
CCryLobby::GetLobbyPacketID()
2874 return ((INetworkPrivate
*)gEnv
->pNetwork
)->FrameIDToHeader(eH_CryLobby
);
2880 #if NETWORK_HOST_MIGRATION
2881 THostMigrationEventListenerContainer
* CCryLobby::GetHostMigrationListeners()
2883 return &m_hostMigrationListeners
;
2887 void CCryLobby::AddHostMigrationEventListener(IHostMigrationEventListener
* pListener
, const char* pWho
, uint32 priority
)
2889 #if NETWORK_HOST_MIGRATION
2890 for (THostMigrationEventListenerContainer::iterator it
= m_hostMigrationListeners
.begin(); it
!= m_hostMigrationListeners
.end(); ++it
)
2892 if (it
->second
.m_pListener
== pListener
)
2894 // The listener is already registered
2899 SHostMigrationEventListenerInfo
info(pListener
, pWho
);
2900 m_hostMigrationListeners
.insert(std::pair
<EListenerPriorityType
, SHostMigrationEventListenerInfo
>((EListenerPriorityType
)priority
, info
));
2904 void CCryLobby::RemoveHostMigrationEventListener(IHostMigrationEventListener
* pListener
)
2906 #if NETWORK_HOST_MIGRATION
2907 for (THostMigrationEventListenerContainer::iterator it
= m_hostMigrationListeners
.begin(); it
!= m_hostMigrationListeners
.end(); ++it
)
2909 if (it
->second
.m_pListener
== pListener
)
2911 m_hostMigrationListeners
.erase(it
);
2918 CCryLobby::CMemAllocator::CMemAllocator()
2920 #ifdef USE_GLOBAL_BUCKET_ALLOCATOR
2921 m_bucketAllocator
.EnableExpandCleanups(false);
2923 m_pGeneralHeap
= CryGetIMemoryManager()->CreateGeneralExpandingMemoryHeap(LOBBY_GENERAL_HEAP_SIZE
, LOBBY_GENERAL_HEAP_SIZE
, "CryLobby General");
2925 m_totalBucketAllocated
= 0;
2926 m_totalGeneralHeapAllocated
= 0;
2927 m_MaxBucketAllocated
= 0;
2928 m_MaxGeneralHeapAllocated
= 0;
2931 CCryLobby::CMemAllocator::~CMemAllocator()
2936 TMemHdl
CCryLobby::CMemAllocator::MemAlloc(size_t sz
)
2940 if (sz
<= m_bucketAllocator
.MaxSize
)
2942 p
= m_bucketAllocator
.allocate(sz
);
2946 CryFatalError("Lobby Allocation For %" PRISIZE_T
" Failed - Suggest increasing the bucket allocator size!!!!", sz
);
2949 m_totalBucketAllocated
+= m_bucketAllocator
.getSize(p
);
2951 if (m_totalBucketAllocated
> m_MaxBucketAllocated
)
2953 m_MaxBucketAllocated
= m_totalBucketAllocated
;
2958 p
= m_pGeneralHeap
->Malloc(sz
, "Lobby");
2962 CryFatalError("Lobby Allocation For %" PRISIZE_T
" Failed - Suggest increasing the general heap size!!!!", sz
);
2965 m_totalGeneralHeapAllocated
+= m_pGeneralHeap
->UsableSize(p
);
2967 if (m_totalGeneralHeapAllocated
> m_MaxGeneralHeapAllocated
)
2969 m_MaxGeneralHeapAllocated
= m_totalGeneralHeapAllocated
;
2976 void CCryLobby::CMemAllocator::MemFree(TMemHdl h
)
2978 void* p
= MemGetPtr(h
);
2980 if (m_bucketAllocator
.IsInAddressRange(p
))
2982 m_totalBucketAllocated
-= m_bucketAllocator
.getSize(p
);
2983 m_bucketAllocator
.deallocate(p
);
2987 m_totalGeneralHeapAllocated
-= m_pGeneralHeap
->UsableSize(p
);
2988 m_pGeneralHeap
->Free(p
);
2992 void* CCryLobby::CMemAllocator::MemGetPtr(TMemHdl h
)
2997 TMemHdl
CCryLobby::CMemAllocator::MemGetHdl(void* ptr
)
3002 void CCryLobby::CMemAllocator::PrintStats()
3004 NetLog("CryLobby Memory Stats");
3005 NetLog("Current Bucket Allocated %" PRISIZE_T
" Maximum Bucket Allocated %" PRISIZE_T
, m_totalBucketAllocated
, m_MaxBucketAllocated
);
3006 NetLog("Current General Heap Allocated %" PRISIZE_T
" Maximum General Heap Allocated %" PRISIZE_T
, m_totalGeneralHeapAllocated
, m_MaxGeneralHeapAllocated
);