!I 1937152 from //dev_game_hunt/consoles_candidate: !B Remove allocations of unnecess...
[CRYENGINE.git] / Code / CryPlugins / CryLobby / Module / PSNOrbis / CryPSN2MatchMaking.cpp
blob37fa6f1247b78facb92775e443d819fc8c77d292
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
5 #include "CrySharedLobbyPacket.h"
7 #if CRY_PLATFORM_ORBIS
9 #include "CryPSN2Lobby.h"
10 #include "CryPSN2Response.h"
11 #include "CryPSN2MatchMaking.h"
13 #if USE_PSN
14 #if USE_CRY_MATCHMAKING
16 #include <CryCore/CryEndian.h>
17 #include <CryGame/IGameFramework.h>
19 #include <libsysmodule.h>
20 #include "CryPSN2WebApi.h"
21 #include "CryPSN2WebApi_Session.h"
23 #define SIGNALING_TIMEOUT (15 * 1000) // 15 seconds using our own timeout code
24 #define PSN_MATCHMAKING_DEFAULT_UNKNOWN_PING (3000)
26 #define MAX_ROOMS_PER_WORLD (5000) //-- Max 5000 rooms available for one world
28 #define PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT (0)
29 #define PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT (1)
31 #define PSN_MATCHMAKING_SEARCH_PARAMS_SLOT (0)
32 #define PSN_MATCHMAKING_SEARCH_DATA_SLOT (1)
33 #define PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT (2)
34 #define PSN_MATCHMAKING_PSNSUPPORT_SEARCH_QOS_SLOT (3)
36 #define PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT (0)
37 #define PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT (1)
38 #define PSN_MATCHMAKING_WEBAPI_JOIN_SLOT (2)
40 #define PSN_MATCHMAKING_CREATE_PARAMS_SLOT (0)
41 #define PSN_MATCHMAKING_CREATE_DATA_SLOT (1)
42 #define PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT (2)
43 #define PSN_MATCHMAKING_WEBAPI_CREATE_SLOT (3)
45 #define PSN_MATCHMAKING_UPDATE_DATA_SLOT (0)
46 #define PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT (1)
48 #define PSN_MATCHMAKING_USERDATA_DATA_SLOT (0)
49 #define PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT (1)
51 #define PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT (0)
52 #define PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT (1)
54 #define PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT (0)
55 #define PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART (1)
57 #define PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT (0)
59 #define PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT (0)
60 #define PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT (1)
62 #define PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT (0)
63 #define PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT (1)
64 #define PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT (2)
66 CryMatchMakingConnectionID CCryPSNMatchMaking::FindConnectionIDFromRoomMemberID(CryLobbySessionHandle sessionHandle, SceNpMatching2RoomMemberId memberId)
68 if ((sessionHandle != CryLobbyInvalidSessionHandle) && (memberId != INVALID_PSN_ROOM_MEMBER_ID))
70 SSession* pSession = &m_sessions[sessionHandle];
71 if (pSession->IsUsed())
73 for (uint32 a = 0; a < MAX_LOBBY_CONNECTIONS; a++)
75 SSession::SRConnection* pConnection = &pSession->remoteConnection[a];
76 if (pConnection->used && pConnection->registered && (pConnection->memberId == memberId))
78 return a;
84 return CryMatchMakingInvalidConnectionID;
87 CCryPSNMatchMaking::SSession::SRoomMember* CCryPSNMatchMaking::FindRoomMemberFromRoomMemberID(CryLobbySessionHandle sessionHandle, SceNpMatching2RoomMemberId memberId)
89 if ((sessionHandle != CryLobbyInvalidSessionHandle) && (memberId != INVALID_PSN_ROOM_MEMBER_ID))
91 SSession* pSession = &m_sessions[sessionHandle];
92 if (pSession->IsUsed())
94 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
96 if (pSession->m_members[a].IsUsed() && (pSession->m_members[a].m_memberId == memberId))
98 return &pSession->m_members[a];
104 return NULL;
107 uint64 CCryPSNMatchMaking::GetSIDFromSessionHandle(CryLobbySessionHandle h)
109 CRY_ASSERT_MESSAGE((h < MAX_MATCHMAKING_SESSIONS) && m_sessions[h].IsUsed(), "CCryPSNMatchMaking::GetSIDFromSessionHandle: invalid session handle");
111 return m_sessions[h].m_roomId;
114 CrySessionID CCryPSNMatchMaking::SessionGetCrySessionIDFromCrySessionHandle(CrySessionHandle gh)
116 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
118 if ((h < MAX_MATCHMAKING_SESSIONS) && m_sessions[h].IsUsed())
120 SCryPSNSessionID* pID = new SCryPSNSessionID;
122 if (pID)
124 pID->m_sessionInfo.m_roomId = m_sessions[h].m_roomId;
125 pID->m_sessionInfo.m_worldId = m_sessions[h].m_worldId;
126 pID->m_sessionInfo.m_serverId = m_sessions[h].m_serverId;
127 pID->m_sessionInfo.m_gameType = m_sessions[h].m_gameType;
128 memcpy(&pID->m_sessionId, &m_sessions[h].m_sessionId, sizeof(pID->m_sessionId));
129 pID->m_fromInvite = false;
131 memcpy(&pID->m_sessionId, &m_sessions[h].m_sessionId, sizeof(SceNpSessionId));
133 return pID;
137 return NULL;
140 TNetAddress CCryPSNMatchMaking::GetHostAddressFromSessionHandle(CrySessionHandle gh)
142 LOBBY_AUTO_LOCK;
144 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
145 SSession* pSession = &m_sessions[h];
147 if (pSession->serverConnectionID != CryMatchMakingInvalidConnectionID)
149 const TNetAddress* pDedicatedServerAddr = m_lobby->GetNetAddress(pSession->remoteConnection[pSession->serverConnectionID].connectionID);
151 if (pDedicatedServerAddr)
153 return *pDedicatedServerAddr;
157 SSession::SRoomMember* pMember = FindRoomMemberFromRoomMemberID(h, pSession->m_ownerMemberId);
158 if (pSession->m_ownerMemberId == pSession->m_myMemberId)
160 return TNetAddress(TLocalNetAddress(m_lobby->GetInternalSocketPort(eCLS_Online)));
163 SIPv4Addr addr4;
164 addr4.addr = ntohl(pMember->m_peerAddr.s_addr);
165 addr4.port = ntohs(pMember->m_peerPort);
167 #if !ENABLE_PLATFORM_PROTOCOL
168 if (m_pService)
170 uint16 connectPort, listenPort;
171 m_pService->GetSocketPorts(connectPort, listenPort);
172 addr4.port = ntohs(connectPort);
174 #endif
176 return TNetAddress(addr4);
179 void CCryPSNMatchMaking::SessionDisconnectRemoteConnection(CrySessionHandle gh, const TNetAddress& addr)
181 // At present i don't need to worry about this
184 void CCryPSNMatchMaking::FreeRemoteConnection(CryLobbySessionHandle h, CryMatchMakingConnectionID id)
186 if (id != CryMatchMakingInvalidConnectionID)
188 SSession* pSession = &m_sessions[h];
189 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
191 if (pConnection->used)
193 SessionUserDataEvent(eCLSE_SessionUserLeave, h, id);
195 CCryMatchMaking::FreeRemoteConnection(h, id);
197 pConnection->registered = false;
198 pConnection->memberId = INVALID_PSN_ROOM_MEMBER_ID;
203 uint32 CCryPSNMatchMaking::GetSessionIDSizeInPacket() const
205 return sizeof(SSynchronisedSessionID);
208 ECryLobbyError CCryPSNMatchMaking::WriteSessionIDToPacket(CrySessionID sessionId, CCryLobbyPacket* pPacket) const
210 if (pPacket)
212 SCryPSNSessionID blank;
214 if (sessionId != CrySessionInvalidID)
216 SCryPSNSessionID* psnID = (SCryPSNSessionID*)sessionId.get();
217 if (psnID)
219 pPacket->WriteData(&psnID->m_sessionInfo, sizeof(psnID->m_sessionInfo));
221 else
223 pPacket->WriteData(&blank.m_sessionInfo, sizeof(blank.m_sessionInfo));
226 else
228 pPacket->WriteData(&blank.m_sessionInfo, sizeof(blank.m_sessionInfo));
231 return eCLE_Success;
234 return eCLE_InternalError;
237 CrySessionID CCryPSNMatchMaking::ReadSessionIDFromPacket(CCryLobbyPacket* pPacket) const
239 if (pPacket)
241 CrySessionID returnId = new SCryPSNSessionID;
242 SCryPSNSessionID* psnID = (SCryPSNSessionID*)returnId.get();
243 if (psnID)
245 SCryPSNSessionID blank;
247 pPacket->ReadData(&psnID->m_sessionInfo, sizeof(psnID->m_sessionInfo));
249 //-- Cannot use the SCryPSNSessionID equals operator because we write more than just the roomId to the packet
250 //-- to signify a null session ID.
251 if ((psnID->m_sessionInfo.m_roomId != blank.m_sessionInfo.m_roomId) ||
252 (psnID->m_sessionInfo.m_worldId != blank.m_sessionInfo.m_worldId) ||
253 (psnID->m_sessionInfo.m_serverId != blank.m_sessionInfo.m_serverId) ||
254 (psnID->m_sessionInfo.m_gameType != blank.m_sessionInfo.m_gameType))
256 //-- assume it's a valid session id if any field does not match the blank
257 return returnId;
262 return CrySessionInvalidID;
265 void CCryPSNMatchMaking::DumpMemberInfo(SSession::SRoomMember* pMember)
267 #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
268 NetLog("%s , uid %d , %d.%d.%d.%d:%d",
269 pMember->m_npId.handle.data,
270 pMember->m_memberId,
271 (pMember->m_peerAddr.s_addr >> 24) & 0xFF, (pMember->m_peerAddr.s_addr >> 16) & 0xFF, (pMember->m_peerAddr.s_addr >> 8) & 0xFF, (pMember->m_peerAddr.s_addr) & 0xFF,
272 pMember->m_peerPort);
273 #endif // #if !defined(_RELEASE) || defined(RELEASE_LOGGING)
276 void CCryPSNMatchMaking::ClearRoomMember(CryLobbySessionHandle sessionHandle, uint32 nMember)
278 if (sessionHandle != CryLobbyInvalidSessionHandle)
280 SSession* pSession = &m_sessions[sessionHandle];
281 SSession::SRoomMember* pMember = &pSession->m_members[nMember];
283 if (pMember->IsUsed())
285 if (pMember->IsValid(ePSNMI_Other))
287 // Remove the player (if we have connection information we will need to drop that here too)
288 CryMatchMakingConnectionID id = FindConnectionIDFromRoomMemberID(sessionHandle, pMember->m_memberId);
289 if (id != CryMatchMakingInvalidConnectionID)
291 // This disconnect should be treated as if it came from the host.
292 SessionDisconnectRemoteConnectionViaNub(sessionHandle, id, eDS_FromID, pSession->hostConnectionID, eDC_Unknown, "Clear Room Member");
296 pMember->m_signalingState = ePSNCS_None;
297 pMember->m_memberId = INVALID_PSN_ROOM_MEMBER_ID;
298 pMember->m_valid = ePSNMI_None;
299 pMember->m_bHostJoinAck = false;
300 memset(pMember->m_userData, 0, sizeof(pMember->m_userData));
305 void CCryPSNMatchMaking::AddRoomMember(CryLobbySessionHandle sessionHandle, const SCryPSNRoomMemberDataInternal& memberInfo, ECryPSNMemberInfo info)
307 if (sessionHandle != CryLobbyInvalidSessionHandle)
309 SSession* pSession = &m_sessions[sessionHandle];
310 if (pSession->IsUsed())
312 SSession::SRoomMember* pMember = NULL;
314 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
316 if (pSession->m_members[a].IsUsed())
318 if (pSession->m_members[a].m_memberId == memberInfo.m_memberId)
320 //-- already exists!
321 CRY_ASSERT_MESSAGE(pSession->m_members[a].m_memberId != memberInfo.m_memberId, "Adding a room member who already exists!");
322 return;
325 else
327 if (pMember == NULL)
329 pMember = &pSession->m_members[a];
334 if (pMember)
336 pMember->m_npId = memberInfo.m_npId;
337 pMember->m_memberId = memberInfo.m_memberId;
338 pMember->m_valid = info;
339 pMember->m_signalingState = ePSNCS_None;
340 pMember->m_bHostJoinAck = false;
342 if (memberInfo.m_numBinAttributes > 0)
344 memcpy(pMember->m_userData, memberInfo.m_binAttributes[0].m_data, CRYLOBBY_USER_DATA_SIZE_IN_BYTES);
347 if (pMember->IsValid(ePSNMI_Me))
349 pSession->m_myMemberId = pMember->m_memberId;
351 pSession->localConnection.uid.m_uid = pMember->m_memberId;
352 pSession->localConnection.uid.m_sid = pSession->m_roomId;
355 if (pMember->IsValid(ePSNMI_Owner))
357 pSession->m_ownerMemberId = pMember->m_memberId;
360 if (pMember->IsValid(ePSNMI_Other))
362 // We don't have connection information yet (ip / port etc)
363 SCryMatchMakingConnectionUID matchingUID;
365 matchingUID.m_uid = pMember->m_memberId;
366 matchingUID.m_sid = pSession->m_roomId;
368 CryMatchMakingConnectionID id = CCryMatchMaking::AddRemoteConnection(sessionHandle, CryLobbyInvalidConnectionID, matchingUID, 1);
369 if (id != CryMatchMakingInvalidConnectionID)
371 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
373 // pConnection->flags |= CMMRC_FLAG_PLATFORM_DATA_VALID;
374 pConnection->registered = true;
375 pConnection->connectionID = CryLobbyInvalidConnectionID;
376 pConnection->memberId = pMember->m_memberId;
378 if ((pSession->localFlags & CRYSESSION_LOCAL_FLAG_HOST) != CRYSESSION_LOCAL_FLAG_HOST)
380 if (!pMember->IsValid(ePSNMI_Owner))
382 //-- If person being added is not the owner, and I am not the owner, send a user joined event to the game immediately -
383 //-- there is no need to wait for signaling to establish.
384 //-- This should allow peers behind strict firewalls to see each other joining
385 //-- but still ensure clients are only added to the server when the signaling establishes.
386 DumpMemberInfo(pMember);
387 AddVoiceUser(pMember);
388 SessionUserDataEvent(eCLSE_SessionUserJoin, sessionHandle, id);
393 //-- Not me, and no peer state defined yet, so lets kick off a peer connection test for this member
394 pMember->m_signalingState = ePSNCS_Pending;
395 pMember->m_signalingTimer = g_time;
402 void CCryPSNMatchMaking::RemoveRoomMember(CryLobbySessionHandle sessionHandle, const SCryPSNRoomMemberDataInternal& memberInfo)
404 if (sessionHandle != CryLobbyInvalidSessionHandle)
406 SSession* pSession = &m_sessions[sessionHandle];
407 if (pSession->IsUsed())
409 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
411 SSession::SRoomMember* pMember = &pSession->m_members[a];
413 if (pMember->IsUsed() && (sceNpCmpNpId(&pMember->m_npId, &memberInfo.m_npId) == 0))
415 ClearRoomMember(sessionHandle, a);
416 return;
423 void CCryPSNMatchMaking::UpdateRoomMember(CryLobbySessionHandle sessionHandle, const SCryPSNRoomMemberDataInternal& updatedMemberInfo)
425 if (sessionHandle != CryLobbyInvalidSessionHandle)
427 SSession* pSession = &m_sessions[sessionHandle];
428 if (pSession->IsUsed())
430 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
432 SSession::SRoomMember* pMember = &pSession->m_members[a];
434 if (pMember->m_valid && (pMember->m_memberId == updatedMemberInfo.m_memberId))
436 if (updatedMemberInfo.m_numBinAttributes > 0)
438 memcpy(pMember->m_userData, updatedMemberInfo.m_binAttributes[0].m_data, CRYLOBBY_USER_DATA_SIZE_IN_BYTES);
441 CryMatchMakingConnectionID id = FindConnectionIDFromRoomMemberID(sessionHandle, pMember->m_memberId);
442 SessionUserDataEvent(eCLSE_SessionUserUpdate, sessionHandle, id);
444 return;
451 void CCryPSNMatchMaking::ClearSessionInfo(CryLobbySessionHandle sessionHandle)
453 assert(sessionHandle != CryLobbyInvalidSessionHandle);
455 if (sessionHandle != CryLobbyInvalidSessionHandle)
457 SSession* pSession = &m_sessions[sessionHandle];
459 if (pSession->IsUsed() && (pSession->m_roomId != INVALID_PSN_ROOM_ID))
461 SceNpMatching2RequestId IDontCareReqId;
462 SceNpMatching2LeaveRoomRequest IDontCareLeaveParam;
464 memset(&IDontCareLeaveParam, 0, sizeof(SceNpMatching2LeaveRoomRequest));
465 IDontCareLeaveParam.roomId = pSession->m_roomId;
467 sceNpMatching2LeaveRoom(m_pPSNSupport->GetMatchmakingContextId(), &IDontCareLeaveParam, NULL, &IDontCareReqId);
468 if (pSession->m_sessionId.data[0] != 0)
470 // TODO: the only trouble here is that leaveSessionParamsHdl needs to be allocated, but when do we free it? There's no task to complete!
471 // m_pPSNSupport->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::LeaveSession, leaveSessionParamsHdl);
475 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
477 ClearRoomMember(sessionHandle, a);
482 void CCryPSNMatchMaking::AddInitialRoomMembers(CryLobbySessionHandle sessionHandle, const SCryPSNRoomMemberDataInternalList& memberList)
484 if (sessionHandle != CryLobbyInvalidSessionHandle)
486 SSession* pSession = &m_sessions[sessionHandle];
487 if (pSession->IsUsed())
489 for (uint32 a = 0; a < memberList.m_numRoomMembers; a++)
491 SCryPSNRoomMemberDataInternal& memberInfo = memberList.m_pRoomMembers[a];
492 uint32 info = ePSNMI_None;
494 if (a == memberList.m_owner)
496 info |= ePSNMI_Owner;
499 if (a == memberList.m_me)
501 info |= ePSNMI_Me;
503 else
505 info |= ePSNMI_Other;
508 AddRoomMember(sessionHandle, memberInfo, (ECryPSNMemberInfo)info);
514 void CCryPSNMatchMaking::DispatchRoomOwnerChangedEvent(TMemHdl mh)
516 UCryLobbyEventData eventData;
517 eventData.pRoomOwnerChanged = (SCryLobbyRoomOwnerChanged*)m_lobby->MemGetPtr(mh);
519 m_lobby->DispatchEvent(eCLSE_RoomOwnerChanged, eventData);
521 m_lobby->MemFree(mh);
524 void CCryPSNMatchMaking::ChangeRoomOwner(CryLobbySessionHandle sessionHandle, SceNpMatching2RoomMemberId prevOwner, SceNpMatching2RoomMemberId newOwner)
526 if (sessionHandle != CryLobbyInvalidSessionHandle)
528 SSession* pSession = &m_sessions[sessionHandle];
529 if (pSession->localFlags & CRYSESSION_LOCAL_FLAG_USED)
531 SSession::SRoomMember* pMember = NULL;
533 pSession->m_ownerMemberId = newOwner;
535 //-- remove the old room owner
536 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
538 pMember = &pSession->m_members[a];
539 if (pMember->m_valid)
541 if (pMember->m_memberId == prevOwner)
543 assert(pMember->m_valid & ePSNMI_Owner);
545 if (pMember->m_valid & ePSNMI_Me)
547 pMember->m_valid = ePSNMI_Me;
549 else
551 pMember->m_valid = ePSNMI_Other;
555 if (pMember->m_memberId == newOwner)
557 if (pMember->m_valid & ePSNMI_Me)
559 pMember->m_valid = ePSNMI_MeOwner;
561 else
563 pMember->m_valid = ePSNMI_OtherOwner;
569 #if NETWORK_HOST_MIGRATION
570 CryLobbySessionHandle h;
572 SCryMatchMakingConnectionUID matchingUID;
574 matchingUID.m_uid = newOwner;
575 matchingUID.m_sid = pSession->m_roomId;
577 FindConnectionFromUID(matchingUID, &h, &pSession->hostConnectionID); // It is valid for the h to be invalid (basically if hostConnectionID comes back with 0 we don't have any remotes - thats allowed!)
579 // Ensure we're migrating the session (covers catastrophic migration, and migration within migration)
580 HostMigrationInitiate(sessionHandle, eDC_Unknown);
581 pSession->hostMigrationInfo.m_newHostAddressValid = true;
582 pSession->newHostUID = matchingUID;
584 SSession::SRoomMember* pRoomMember = FindRoomMemberFromRoomMemberID(sessionHandle, newOwner);
586 if (pRoomMember)
588 if (pRoomMember->IsValid(ePSNMI_Other) && (pRoomMember->m_signalingState == ePSNCS_Active))
590 if (m_lobby)
592 TMemHdl mh = m_lobby->MemAlloc(sizeof(SCryLobbyRoomOwnerChanged));
593 if (mh != TMemInvalidHdl)
595 SCryLobbyRoomOwnerChanged* pOwnerData = (SCryLobbyRoomOwnerChanged*)m_lobby->MemGetPtr(mh);
597 pOwnerData->m_session = CreateGameSessionHandle(sessionHandle, pSession->localConnection.uid);
598 pOwnerData->m_port = pRoomMember->m_peerPort;
599 pOwnerData->m_ip = pRoomMember->m_peerAddr.s_addr;
601 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::DispatchRoomOwnerChangedEvent, this, mh);
606 #endif
611 void CCryPSNMatchMaking::UpdateSignaling(CryMatchMakingTaskID mmTaskID)
613 STask* pTask = &m_task[mmTaskID];
615 if (pTask->used && pTask->running && (pTask->session != CryLobbyInvalidSessionHandle))
617 SSession* pSession = &m_sessions[pTask->session];
618 if (pSession->IsUsed())
620 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
622 SSession::SRoomMember* pMember = &pSession->m_members[a];
624 if (pMember->IsUsed())
626 //-- Timed out?
627 bool bTestTimeout = false;
629 if (pMember->m_signalingState == ePSNCS_Pending)
631 bTestTimeout = true;
633 else
635 if ((pTask->startedTask == eT_SessionJoin) && pMember->IsValid(ePSNMI_Owner) && (pMember->m_signalingState == ePSNCS_Active) && (pMember->m_bHostJoinAck == false))
637 bTestTimeout = true;
641 if (bTestTimeout)
643 if ((g_time.GetMilliSecondsAsInt64() - pMember->m_signalingTimer.GetMilliSecondsAsInt64()) > SIGNALING_TIMEOUT)
645 pMember->m_signalingState = ePSNCS_Dead;
647 CryMatchMakingConnectionID id = FindConnectionIDFromRoomMemberID(pTask->session, pMember->m_memberId);
648 if (id != CryMatchMakingInvalidConnectionID)
650 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
651 NetLog("[Lobby] CCryPSNMatchMaking::UpdateSignaling() : Signaling dead event setting connection " PRFORMAT_LCID " to eCLCS_NotConnected", PRARG_LCID(pConnection->connectionID));
652 m_lobby->ConnectionSetState(pConnection->connectionID, eCLCS_NotConnected);
662 CCryPSNMatchMaking::ECryPSNConnectionState CCryPSNMatchMaking::CheckSignaling(CryMatchMakingTaskID mmTaskID)
664 STask* pTask = &m_task[mmTaskID];
666 if (pTask->used && pTask->running && (pTask->session != CryLobbyInvalidSessionHandle))
668 SSession* pSession = &m_sessions[pTask->session];
669 if (pSession->IsUsed())
671 //-- If we can talk to the room owner, we'll allow the session state machine to run
672 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
674 SSession::SRoomMember* pMember = &pSession->m_members[a];
676 if (pMember->IsValid(ePSNMI_Owner))
678 //-- Are we the owner?
679 if (pMember->IsValid(ePSNMI_Me))
681 //-- technically, 'me' always has a signaling state of ePSNMI_None, so we'll fake it just for this return.
682 return ePSNCS_Active;
685 //-- Is peer connection to remote owner active?
686 if (pMember->m_signalingState == ePSNCS_Active)
688 if (pMember->m_bHostJoinAck)
690 return ePSNCS_Active;
692 else
694 return ePSNCS_Pending;
698 return pMember->m_signalingState;
704 //-- No owner at all! This is wrong!
705 return ePSNCS_None;
708 bool CCryPSNMatchMaking::ProcessCorrectTaskForRequest(SCryPSNSupportCallbackEventData& data, ETask subTaskCheck, const char* pRequestString, EventRequestResponseCallback pCB)
710 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
712 STask* pTask = &m_task[i];
713 if (pTask->used && pTask->running)
715 if (pTask->m_reqId == data.m_requestEvent.m_reqId)
717 bool bHandled = false;
719 if (pTask->subTask == subTaskCheck)
721 bHandled = pCB(this, pTask, i, data);
723 if (bHandled)
725 data.m_requestEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED;
727 else
729 data.m_requestEvent.m_returnFlags = SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_NOT_HANDLED;
731 // a task was found, but not handled. mark the task with an error so it stops itself
733 // Some generic behaviours for non-critical errors
734 switch (data.m_requestEvent.m_error)
736 case SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND:
737 case SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM:
738 case SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM_INSTANCE:
740 UpdateTaskError(i, eCLE_RoomDoesNotExist);
741 data.m_requestEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED;
743 break;
744 case SCE_NP_MATCHING2_SERVER_ERROR_ROOM_FULL:
746 UpdateTaskError(i, eCLE_SessionFull);
747 data.m_requestEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED;
749 break;
750 default:
752 UpdateTaskError(i, eCLE_InternalError);
753 // If we leave it unhandled, PSNSupport will attempt to handle any critical errors for us
755 break;
759 pTask->m_reqId = INVALID_PSN_REQUEST_ID;
761 if (pTask->error != eCLE_Success)
763 StopTaskRunning(i);
766 return bHandled;
772 NetLog("%s event received, but no tasks in correct state to process it!", pRequestString);
773 return false;
776 bool CCryPSNMatchMaking::ProcessCorrectTaskForSearch(SCryPSNSupportCallbackEventData& data, ETask subTaskCheck, const char* pRequestString, EventRequestResponseCallback pCB)
778 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
780 STask* pTask = &m_task[i];
781 if (pTask->used && pTask->running)
783 if (pTask->subTask == subTaskCheck)
785 assert(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT] != TMemInvalidHdl);
787 SSearchInfoData* pSearchInfo = (SSearchInfoData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
788 if (pSearchInfo)
790 for (int a = 0; a < pSearchInfo->m_numResults; a++)
792 if (data.m_requestEvent.m_reqId == pSearchInfo->m_reqId[a])
794 pTask->m_reqId = data.m_requestEvent.m_reqId;
796 bool bHandled = pCB(this, pTask, i, data);
798 if (bHandled)
800 data.m_requestEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_HANDLED;
802 else
804 data.m_requestEvent.m_returnFlags = SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_NOT_HANDLED;
806 // a task was found, but not handled, stop the task.
807 // If we leave it unhandled, the PSNSupport will attempt to handle any critical errors for us
808 UpdateTaskError(i, eCLE_InternalError);
811 pTask->m_reqId = INVALID_PSN_REQUEST_ID;
813 if (pTask->error != eCLE_Success)
815 StopTaskRunning(i);
818 return bHandled;
822 else
824 // no search info
825 NetLog("%s event received, task %d found with correct subtask %d, but no pSearchInfo!", pRequestString, i, subTaskCheck);
826 UpdateTaskError(i, eCLE_OutOfMemory);
827 StopTaskRunning(i);
828 return false;
834 NetLog("%s event received, but no tasks in correct state to process it!", pRequestString);
835 return false;
838 void CCryPSNMatchMaking::ProcessRequestEvent(SCryPSNSupportCallbackEventData& data)
840 switch (data.m_requestEvent.m_event)
842 case REQUEST_EVENT_GET_WORLD_INFO_LIST:
844 if (!ProcessCorrectTaskForRequest(data, eST_WaitingForCreateRoomWorldInfo, "REQUEST_EVENT_GET_WORLD_INFO_LIST", EventRequestResponse_GetWorldInfoListForCreate))
846 NetLog("Not a create, so trying search instead...");
847 if (!ProcessCorrectTaskForRequest(data, eST_WaitingForSearchRoomWorldInfo, "REQUEST_EVENT_GET_WORLD_INFO_LIST", EventRequestResponse_GetWorldInfoListForSearch))
849 NetLog("Not a search either! Time to trigger unhandled REQUEST_EVENT_GET_WORLD_INFO_LIST!");
853 break;
854 case REQUEST_EVENT_LEAVE_ROOM:
856 ProcessCorrectTaskForRequest(data, eST_WaitingForLeaveRoomRequestCallback, "REQUEST_EVENT_LEAVE_ROOM", EventRequestResponse_LeaveRoom);
858 break;
859 case REQUEST_EVENT_SET_ROOM_MEMBER_DATA_INTERNAL:
861 ProcessCorrectTaskForRequest(data, eST_WaitingForUserDataRequestCallback, "REQUEST_EVENT_SET_ROOM_MEMBER_DATA_INTERNAL", EventRequestResponse_SetRoomMemberDataInternal);
863 break;
864 case REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL:
866 ProcessCorrectTaskForRequest(data, eST_WaitingForUpdateRoomRequestCallback, "REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL", EventRequestResponse_SetRoomDataExternal);
868 break;
869 case REQUEST_EVENT_SET_ROOM_DATA_INTERNAL:
871 #if NETWORK_HOST_MIGRATION
872 ProcessCorrectTaskForRequest(data, eST_WaitingForNewHostHintCallback, "REQUEST_EVENT_SET_ROOM_DATA_INTERNAL", EventRequestResponse_SetRoomDataInternal);
873 #endif
875 break;
876 case REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST:
878 ProcessCorrectTaskForRequest(data, eST_WaitingForQueryRoomRequestCallback, "REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST", EventRequestResponse_GetRoomDataExternalList);
880 break;
881 case REQUEST_EVENT_SEARCH_ROOM:
883 ProcessCorrectTaskForRequest(data, eST_WaitingForSearchRoomRequestCallback, "REQUEST_EVENT_SEARCH_ROOM", EventRequestResponse_SearchRoom);
885 break;
886 case REQUEST_EVENT_SIGNALING_GET_PING_INFO:
888 ProcessCorrectTaskForSearch(data, eST_WaitingForSearchQOSRequestCallback, "REQUEST_EVENT_SIGNALING_GET_PING_INFO", EventRequestResponse_SearchQOS);
890 break;
891 case REQUEST_EVENT_JOIN_ROOM:
893 ProcessCorrectTaskForRequest(data, eST_WaitingForJoinRoomRequestCallback, "REQUEST_EVENT_JOIN_ROOM", EventRequestResponse_JoinRoom);
895 break;
896 case REQUEST_EVENT_CREATE_JOIN_ROOM:
898 ProcessCorrectTaskForRequest(data, eST_WaitingForCreateRoomRequestCallback, "REQUEST_EVENT_CREATE_JOIN_ROOM", EventRequestResponse_CreateRoom);
900 break;
901 case REQUEST_EVENT_GRANT_ROOM_OWNER:
903 #if NETWORK_HOST_MIGRATION
904 ProcessCorrectTaskForRequest(data, eST_WaitingForGrantRoomOwnerRequestCallback, "REQUEST_EVENT_GRANT_ROOM_OWNER", EventRequestResponse_GrantRoomOwner);
905 #endif
907 break;
908 default:
909 break;
910 } //-- switch
913 void CCryPSNMatchMaking::ProcessSignalingEvent(SCryPSNSupportCallbackEventData& data)
915 for (uint32 i = 0; i < MAX_MATCHMAKING_SESSIONS; i++)
917 SSession* pSession = &m_sessions[i];
919 if (pSession->IsUsed())
921 SSession::SRoomMember* pMember = FindRoomMemberFromRoomMemberID(i, data.m_signalEvent.m_subject);
922 if (pMember && pMember->IsValid(ePSNMI_Other) && (pMember->m_signalingState != ePSNCS_None))
924 switch (data.m_signalEvent.m_event)
926 case SIGNALING_EVENT_DEAD:
928 pMember->m_signalingState = ePSNCS_Dead;
930 DumpMemberInfo(pMember);
931 CryMatchMakingConnectionID id = FindConnectionIDFromRoomMemberID(i, pMember->m_memberId);
932 if (id != CryMatchMakingInvalidConnectionID)
934 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
935 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SCE_NP_SIGNALING_EVENT_DEAD : Signaling dead event setting connection " PRFORMAT_LCID " to eCLCS_NotConnected", PRARG_LCID(pConnection->connectionID));
936 NetLog("[Lobby] Signaling ID %d: SIGNALING_EVENT_DEAD not handled: error %08X", data.m_signalEvent.m_subject, data.m_signalEvent.m_error);
937 m_lobby->ConnectionSetState(pConnection->connectionID, eCLCS_NotConnected);
940 data.m_signalEvent.m_bHandled = true;
942 break;
944 case SIGNALING_EVENT_CONNECTED:
946 int conStatus;
947 int ret = sceNpMatching2SignalingGetConnectionStatus(m_pPSNSupport->GetMatchmakingContextId(), data.m_signalEvent.m_roomId, data.m_signalEvent.m_subject, &conStatus, (SceNetInAddr*)&pMember->m_peerAddr, &pMember->m_peerPort);
948 if ((ret == PSN_OK) && (conStatus == SCE_NP_MATCHING2_SIGNALING_CONN_STATUS_ACTIVE))
950 pMember->m_signalingState = ePSNCS_Active;
952 CryMatchMakingConnectionID id = FindConnectionIDFromRoomMemberID(i, pMember->m_memberId);
953 if (id != CryMatchMakingInvalidConnectionID)
955 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
957 if (pConnection->connectionID == CryLobbyInvalidConnectionID)
959 TNetAddress netAddr = TNetAddress(SIPv4Addr(ntohl(pMember->m_peerAddr.s_addr), ntohs(pMember->m_peerPort)));
961 #if !ENABLE_PLATFORM_PROTOCOL
962 if (m_pService)
964 uint16 connectPort, listenPort;
966 m_pService->GetSocketPorts(connectPort, listenPort);
967 netAddr = TNetAddress(SIPv4Addr(ntohl(pMember->m_peerAddr.s_addr), connectPort));
969 #endif
970 // Add connection - if not found
971 CryLobbyConnectionID lID = m_lobby->FindConnection(netAddr);
972 if (lID == CryLobbyInvalidConnectionID)
974 lID = m_lobby->CreateConnection(netAddr);
976 else
978 if (m_lobby->ConnectionGetState(lID) == eCLCS_Freeing)
980 NetLog("[Lobby] Signaling active on existing Freeing connection " PRFORMAT_LCID, PRARG_LCID(lID));
981 m_lobby->FreeConnection(lID);
982 lID = m_lobby->CreateConnection(netAddr);
986 m_lobby->ConnectionAddRef(lID);
987 pConnection->connectionID = lID;
989 DumpMemberInfo(pMember);
990 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SIGNALING_EVENT_CONNECTED : Signaling established for " PRFORMAT_SHMMCINFO, PRARG_SHMMCINFO(CryLobbySessionHandle(i), id, pConnection->connectionID, pConnection->uid));
992 AddVoiceUser(pMember);
993 SessionUserDataEvent(eCLSE_SessionUserJoin, i, id);
995 if (pSession->localFlags & CRYSESSION_LOCAL_FLAG_HOST)
997 // Include the SceNpSessionId the host got from registering the session on PSN when room was created.
998 // Pass this over to all connecting clients so they can join the same session
999 const uint32 maxBufferSize = CryLobbyPacketHeaderSize + sizeof(SceNpSessionId);
1000 uint8 buffer[maxBufferSize];
1001 CCryLobbyPacket packet;
1003 packet.SetWriteBuffer(buffer, maxBufferSize);
1004 packet.StartWrite(ePSNPT_JoinSessionAck, true);
1005 packet.WriteString((const char*)&pSession->m_sessionId, sizeof(SceNpSessionId));
1007 Send(CryMatchMakingInvalidTaskID, &packet, i, id);
1012 else if (ret < PSN_OK)
1014 NetLog("sceNpMatching2SignalingGetConnectionStatus : %08X", ret);
1016 pMember->m_signalingState = ePSNCS_Dead;
1018 CryMatchMakingConnectionID id = FindConnectionIDFromRoomMemberID(i, pMember->m_memberId);
1019 if (id != CryMatchMakingInvalidConnectionID)
1021 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
1022 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SIGNALING_EVENT_CONNECTED(1) : Signaling connected failure event, setting " PRFORMAT_SHMMCINFO " to eCLCS_NotConnected", PRARG_SHMMCINFO(CryLobbySessionHandle(i), id, pConnection->connectionID, pConnection->uid));
1023 m_lobby->ConnectionSetState(pConnection->connectionID, eCLCS_NotConnected);
1026 m_pPSNSupport->HandlePSNError(ret);
1028 else
1030 pMember->m_signalingState = ePSNCS_Dead;
1032 CryMatchMakingConnectionID id = FindConnectionIDFromRoomMemberID(i, pMember->m_memberId);
1033 if (id != CryMatchMakingInvalidConnectionID)
1035 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
1036 NetLog("[Lobby] CCryPSNMatchMaking::ProcessSignalingEvent() : SIGNALING_EVENT_CONNECTED(2) : Signaling connected failure event, setting " PRFORMAT_SHMMCINFO " to eCLCS_NotConnected", PRARG_SHMMCINFO(CryLobbySessionHandle(i), id, pConnection->connectionID, pConnection->uid));
1037 m_lobby->ConnectionSetState(pConnection->connectionID, eCLCS_NotConnected);
1040 data.m_signalEvent.m_bHandled = true;
1042 break;
1044 case SIGNALING_EVENT_NETINFO_RESULT:
1046 NetLog("[SIGNALING] Ignored Event : %08X", data.m_signalEvent.m_event);
1047 data.m_signalEvent.m_bHandled = true;
1049 break;
1051 default:
1052 // handle unknown responses - future sdks
1053 break;
1060 void CCryPSNMatchMaking::DispatchForcedFromRoomEvent(CrySessionHandle gh, SceNpMatching2Event how, SceNpMatching2EventCause why)
1062 if (m_lobby)
1064 UCryLobbyEventData eventData;
1065 SCryLobbyForcedFromRoomData eventRoomData;
1066 eventData.pForcedFromRoomData = &eventRoomData;
1068 eventRoomData.m_session = gh;
1070 switch (why)
1072 case SCE_NP_MATCHING2_EVENT_CAUSE_SERVER_OPERATION:
1073 case SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION:
1075 NetLog("DispatchForcedFromRoomEvent(eFFRR_ServerForced)");
1076 eventRoomData.m_why = eFFRR_ServerForced;
1078 break;
1079 case SCE_NP_MATCHING2_EVENT_CAUSE_LEAVE_ACTION:
1080 case SCE_NP_MATCHING2_EVENT_CAUSE_MEMBER_DISAPPEARED:
1082 NetLog("DispatchForcedFromRoomEvent(eFFRR_Left)");
1083 eventRoomData.m_why = eFFRR_Left;
1085 break;
1086 case SCE_NP_MATCHING2_EVENT_CAUSE_KICKOUT_ACTION:
1088 NetLog("DispatchForcedFromRoomEvent(eFFRR_Kicked)");
1089 eventRoomData.m_why = eFFRR_Kicked;
1091 break;
1092 case SCE_NP_MATCHING2_EVENT_CAUSE_SERVER_INTERNAL:
1093 case SCE_NP_MATCHING2_EVENT_CAUSE_SYSTEM_ERROR:
1094 case SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ERROR:
1096 NetLog("DispatchForcedFromRoomEvent(eFFRR_ServerInternalError)");
1097 eventRoomData.m_why = eFFRR_ServerInternalError;
1099 break;
1100 case SCE_NP_MATCHING2_EVENT_CAUSE_CONNECTION_ERROR:
1102 NetLog("DispatchForcedFromRoomEvent(eFFRR_ConnectionError)");
1103 eventRoomData.m_why = eFFRR_ConnectionError;
1105 break;
1106 case SCE_NP_MATCHING2_EVENT_CAUSE_NP_SIGNED_OUT:
1108 NetLog("DispatchForcedFromRoomEvent(eFFRR_SignedOut)");
1109 eventRoomData.m_why = eFFRR_SignedOut;
1111 break;
1112 default:
1114 NetLog("DispatchForcedFromRoomEvent(eFFRR_Unknown)");
1115 eventRoomData.m_why = eFFRR_Unknown;
1117 break;
1120 m_lobby->DispatchEvent(eCLSE_ForcedFromRoom, eventData);
1124 void CCryPSNMatchMaking::ProcessRoomEvent(SCryPSNSupportCallbackEventData& data)
1126 for (uint32 i = 0; i < MAX_MATCHMAKING_SESSIONS; i++)
1128 SSession* pSession = &m_sessions[i];
1130 if (pSession->IsUsed() && (pSession->m_roomId == data.m_roomEvent.m_roomId))
1132 switch (data.m_roomEvent.m_event)
1134 case ROOM_EVENT_MEMBER_JOINED:
1136 if ((data.m_roomEvent.m_error == 0) &&
1137 (data.m_roomEvent.m_dataHdl != TMemInvalidHdl) &&
1138 (data.m_roomEvent.m_dataSize == sizeof(SCryPSNRoomMemberUpdateInfoResponse)))
1140 SCryPSNRoomMemberUpdateInfoResponse* pMemberUpdateInfo = (SCryPSNRoomMemberUpdateInfoResponse*)m_pPSNSupport->GetLobby()->MemGetPtr(data.m_roomEvent.m_dataHdl);
1142 if (pMemberUpdateInfo->m_member.m_flagAttr & SCE_NP_MATCHING2_ROOMMEMBER_FLAG_ATTR_OWNER)
1144 AddRoomMember(i, pMemberUpdateInfo->m_member, ePSNMI_OtherOwner);
1146 else
1148 AddRoomMember(i, pMemberUpdateInfo->m_member, ePSNMI_Other);
1151 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1153 else
1155 //-- error occurred on room member join event
1156 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1159 break;
1160 case ROOM_EVENT_MEMBER_LEFT:
1162 if ((data.m_roomEvent.m_error == 0) &&
1163 (data.m_roomEvent.m_dataHdl != TMemInvalidHdl) &&
1164 (data.m_roomEvent.m_dataSize == sizeof(SCryPSNRoomMemberUpdateInfoResponse)))
1166 SCryPSNRoomMemberUpdateInfoResponse* pMemberUpdateInfo = (SCryPSNRoomMemberUpdateInfoResponse*)m_pPSNSupport->GetLobby()->MemGetPtr(data.m_roomEvent.m_dataHdl);
1167 RemoveRoomMember(i, pMemberUpdateInfo->m_member);
1169 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1171 else
1173 //-- error occurred on room member left event
1174 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1177 break;
1178 case ROOM_EVENT_ROOM_OWNER_CHANGED:
1180 if ((data.m_roomEvent.m_error == 0) &&
1181 (data.m_roomEvent.m_dataHdl != TMemInvalidHdl) &&
1182 (data.m_roomEvent.m_dataSize == sizeof(SCryPSNRoomOwnerUpdateInfoResponse)))
1184 SCryPSNRoomOwnerUpdateInfoResponse* pOwnerInfo = (SCryPSNRoomOwnerUpdateInfoResponse*)m_pPSNSupport->GetLobby()->MemGetPtr(data.m_roomEvent.m_dataHdl);
1185 NetLog("[LEE] Got Request for room owner change : Old Owner %d, New Owner %d", pOwnerInfo->m_prevOwner, pOwnerInfo->m_newOwner);
1186 ChangeRoomOwner(i, pOwnerInfo->m_prevOwner, pOwnerInfo->m_newOwner);
1188 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1190 else
1192 //-- error occurred on room owner changed event
1193 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1196 break;
1197 case ROOM_EVENT_KICKED_OUT:
1199 NetLog("ROOM_EVENT_KICKED_OUT i:%d", i);
1201 if ((data.m_roomEvent.m_error == 0) &&
1202 (data.m_roomEvent.m_dataHdl != TMemInvalidHdl) &&
1203 (data.m_roomEvent.m_dataSize == sizeof(SCryPSNRoomUpdateInfoResponse)))
1205 ClearSessionInfo(i);
1206 FreeSessionHandle(i);
1208 SCryPSNRoomUpdateInfoResponse* pUpdateInfo = (SCryPSNRoomUpdateInfoResponse*)m_pPSNSupport->GetLobby()->MemGetPtr(data.m_roomEvent.m_dataHdl);
1210 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::DispatchForcedFromRoomEvent, this, CreateGameSessionHandle(i, pSession->localConnection.uid), data.m_roomEvent.m_event, pUpdateInfo->m_eventCause);
1212 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1214 else
1216 //-- error occurred on kicked out of room event
1217 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1220 break;
1221 case ROOM_EVENT_ROOM_DESTROYED:
1223 if ((data.m_roomEvent.m_error == 0) &&
1224 (data.m_roomEvent.m_dataHdl != TMemInvalidHdl) &&
1225 (data.m_roomEvent.m_dataSize == sizeof(SCryPSNRoomUpdateInfoResponse)))
1227 ClearSessionInfo(i);
1228 FreeSessionHandle(i);
1230 SCryPSNRoomUpdateInfoResponse* pUpdateInfo = (SCryPSNRoomUpdateInfoResponse*)m_pPSNSupport->GetLobby()->MemGetPtr(data.m_roomEvent.m_dataHdl);
1232 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::DispatchForcedFromRoomEvent, this, CreateGameSessionHandle(i, pSession->localConnection.uid), data.m_roomEvent.m_event, pUpdateInfo->m_eventCause);
1234 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1236 else
1238 //-- error occurred on room destroyed event
1239 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1242 break;
1243 case ROOM_EVENT_UPDATED_ROOM_DATA_INTERNAL:
1245 //-- Don't actually care about this event:- we just trap it so it doesn't get flagged as unhandled.
1246 if (data.m_roomEvent.m_error == 0)
1248 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1250 else
1252 //-- error occurred on internal room data updated event
1253 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1256 break;
1257 case ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL:
1259 if ((data.m_roomEvent.m_error == 0) &&
1260 (data.m_roomEvent.m_dataHdl != TMemInvalidHdl) &&
1261 (data.m_roomEvent.m_dataSize == sizeof(SCryPSNRoomMemberUpdateInfoResponse)))
1264 const SCryPSNRoomMemberUpdateInfoResponse* const pUpdateInfo = (SCryPSNRoomMemberUpdateInfoResponse*)m_pPSNSupport->GetLobby()->MemGetPtr(data.m_requestEvent.m_dataHdl);
1265 UpdateRoomMember(i, pUpdateInfo->m_member);
1267 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1269 else
1271 //-- error occurred on internal room member data updated event
1272 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1275 break;
1276 case ROOM_EVENT_UPDATED_SIGNALING_OPT_PARAM:
1278 //-- Don't actually care about this event:- we just trap it so it doesn't get flagged as unhandled.
1279 if (data.m_roomEvent.m_error == 0)
1281 data.m_roomEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRoomEvent::ROOM_EVENT_HANDLED;
1283 else
1285 //-- error occurred on signaling opt param updated event
1286 //-- leave data.m_roomEvent.m_returnFlags as 0 to let the default error handler take care of any serious errors.
1289 break;
1292 return;
1297 void CCryPSNMatchMaking::ProcessErrorEvent(SCryPSNSupportCallbackEventData& data)
1299 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
1301 STask* pTask = &m_task[i];
1302 if (pTask->used && pTask->running)
1304 UpdateTaskError(i, MapSupportErrorToLobbyError(data.m_errorEvent.m_error));
1305 StopTaskRunning(i);
1309 for (uint32 j = 0; j < MAX_MATCHMAKING_SESSIONS; j++)
1311 SSession* pSession = &m_sessions[j];
1312 if (pSession->IsUsed())
1314 ClearSessionInfo(j);
1315 FreeSessionHandle(j);
1320 void CCryPSNMatchMaking::ProcessWebApiEvent(SCryPSNSupportCallbackEventData& data)
1322 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
1324 STask* pTask = &m_task[i];
1325 if (pTask->used && pTask->running)
1327 switch (pTask->subTask)
1329 case eST_WaitingForCreateRoomWebApiCallback:
1331 SCreateParamData* pCreateParams = (SCreateParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT]);
1332 if (pCreateParams && (pCreateParams->m_createJobId == data.m_webApiEvent.m_id))
1334 EventWebApiCreateSession(i, data);
1335 data.m_webApiEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED;
1338 break;
1339 case eST_WaitingForJoinRoomWebApiCallback:
1341 SJoinParamData* pJoinParams = (SJoinParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT]);
1342 if (pJoinParams && (pJoinParams->m_joinJobId == data.m_webApiEvent.m_id))
1344 EventWebApiJoinSession(i, data);
1345 data.m_webApiEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED;
1348 break;
1349 case eST_WaitingForLeaveRoomWebApiCallback:
1351 SLeaveParamData* pLeaveParams = (SLeaveParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT]);
1352 if (pLeaveParams && (pLeaveParams->m_leaveJobId == data.m_webApiEvent.m_id))
1354 EventWebApiLeaveSession(i, data);
1355 data.m_webApiEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED;
1358 break;
1359 case eST_WaitingForUpdateAdvertisementDataWebApiCallback:
1361 SUpdateAdvertisementDataParamData* pAdParams = (SUpdateAdvertisementDataParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT]);
1362 if (pAdParams && (pAdParams->m_jobId == data.m_webApiEvent.m_id))
1364 EventWebApiUpdateSessionAdvertisement(i, data);
1365 data.m_webApiEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED;
1368 break;
1369 case eST_WaitingForGetAdvertisementDataWebApiCallback:
1371 SGetAdvertisementDataParamData* pAdParams = (SGetAdvertisementDataParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT]);
1372 if (pAdParams && (pAdParams->m_jobId == data.m_webApiEvent.m_id))
1374 EventWebApiGetSessionLinkData(i, data);
1375 data.m_webApiEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SWebApiEvent::WEBAPI_EVENT_HANDLED;
1378 break;
1384 void CCryPSNMatchMaking::SupportCallback(ECryPSNSupportCallbackEvent ecb, SCryPSNSupportCallbackEventData& data, void* pArg)
1386 CCryPSNMatchMaking* _this = static_cast<CCryPSNMatchMaking*>(pArg);
1388 switch (ecb)
1390 case eCE_RequestEvent:
1392 _this->ProcessRequestEvent(data);
1394 break;
1395 case eCE_SignalEvent:
1397 _this->ProcessSignalingEvent(data);
1399 break;
1400 case eCE_RoomEvent:
1402 _this->ProcessRoomEvent(data);
1404 break;
1405 case eCE_ErrorEvent:
1407 _this->ProcessErrorEvent(data);
1409 break;
1410 case eCE_WebApiEvent:
1412 _this->ProcessWebApiEvent(data);
1414 break;
1418 ECryLobbyError CCryPSNMatchMaking::Initialise()
1420 ECryLobbyError error = CCryMatchMaking::Initialise();
1422 if (error == eCLE_Success)
1424 int ret;
1426 ret = sceSysmoduleLoadModule(SCE_SYSMODULE_NP_MATCHING2);
1427 if (ret < PSN_OK)
1429 NetLog("sceSysmoduleLoadModule(SCE_SYSMODULE_NP_MATCHING2) failed. ret = 0x%x\n", ret);
1430 return eCLE_InternalError;
1433 SceNpMatching2InitializeParameter configurationMatching2;
1434 memset(&configurationMatching2, 0, sizeof(configurationMatching2));
1435 configurationMatching2.size = sizeof(configurationMatching2);
1436 configurationMatching2.poolSize = SCE_NP_MATCHING2_POOLSIZE_DEFAULT;
1437 configurationMatching2.cpuAffinityMask = SCE_KERNEL_CPUMASK_USER_ALL;
1438 configurationMatching2.threadPriority = SCE_KERNEL_PRIO_FIFO_DEFAULT; //CLobbyCVars::Get().psnMatching2ThreadPriority;
1439 configurationMatching2.threadStackSize = SCE_NP_MATCHING2_THREAD_STACK_SIZE_DEFAULT;
1441 ret = sceNpMatching2Initialize(&configurationMatching2);
1442 if (ret < PSN_OK)
1444 NetLog("sceNpMatching2Initialize() failed. ret = 0x%x\n", ret);
1445 return eCLE_InternalError;
1448 m_registeredUserData.num = 0;
1450 for (uint32 i = 0; i < MAX_MATCHMAKING_SESSIONS; i++)
1452 m_sessions[i].localFlags &= ~CRYSESSION_LOCAL_FLAG_USED;
1454 for (uint32 j = 0; j < MAX_LOBBY_CONNECTIONS; j++)
1456 m_sessions[i].remoteConnection[j].connectionID = CryLobbyInvalidConnectionID;
1457 m_sessions[i].remoteConnection[j].used = false;
1458 m_sessions[i].remoteConnection[j].registered = false;
1459 m_sessions[i].remoteConnection[j].memberId = INVALID_PSN_ROOM_MEMBER_ID;
1462 ClearSessionInfo(i);
1465 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
1467 m_task[i].m_reqId = INVALID_PSN_REQUEST_ID;
1471 return error;
1474 ECryLobbyError CCryPSNMatchMaking::Terminate()
1476 for (uint32 i = 0; i < MAX_MATCHMAKING_SESSIONS; i++)
1478 SSession* pSession = &m_sessions[i];
1479 if (pSession->IsUsed())
1481 ClearSessionInfo(i);
1482 FreeSessionHandle(i);
1486 int ret;
1487 ret = sceNpMatching2Terminate();
1488 if (ret < PSN_OK)
1490 NetLog("sceNpMatching2Termimate() failed. ret = 0x%x\n", ret);
1493 ret = sceSysmoduleUnloadModule(SCE_SYSMODULE_NP_MATCHING2);
1494 if (ret < PSN_OK)
1496 NetLog("sceSysmoduleUnloadModule(SCE_SYSMODULE_NP_MATCHING2) failed. ret = 0x%x\n", ret);
1499 return eCLE_Success;
1502 CCryPSNMatchMaking::CCryPSNMatchMaking(CCryLobby* lobby, CCryLobbyService* service, CCryPSNSupport* pSupport, ECryLobbyService serviceType) : CCryMatchMaking(lobby, service, serviceType)
1504 m_pPSNSupport = pSupport;
1506 m_oldNatType = SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_UNKNOWN;
1508 // Make the CCryMatchMaking base pointers point to our data so we can use the common code in CCryMatchMaking
1509 for (uint32 i = 0; i < MAX_MATCHMAKING_SESSIONS; i++)
1511 CCryMatchMaking::m_sessions[i] = &m_sessions[i];
1512 CCryMatchMaking::m_sessions[i]->localConnection = &m_sessions[i].localConnection;
1514 for (uint32 j = 0; j < MAX_LOBBY_CONNECTIONS; j++)
1516 CCryMatchMaking::m_sessions[i]->remoteConnection[j] = &m_sessions[i].remoteConnection[j];
1520 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
1522 CCryMatchMaking::m_task[i] = &m_task[i];
1525 REGISTER_CVAR2("net_enable_psn_hinting", &net_enable_psn_hinting, 1, VF_DUMPTODISK, "Toggles whether PSN hinting enabled or not");
1528 CCryPSNMatchMaking::~CCryPSNMatchMaking()
1532 ECryLobbyError CCryPSNMatchMaking::StartTask(ETask etask, bool startRunning, uint32 user, CryMatchMakingTaskID* mmTaskID, CryLobbyTaskID* lTaskID, CryLobbySessionHandle h, void* cb, void* cbArg)
1534 CryMatchMakingTaskID tmpMMTaskID;
1535 CryMatchMakingTaskID* useMMTaskID = mmTaskID ? mmTaskID : &tmpMMTaskID;
1536 ECryLobbyError error = CCryMatchMaking::StartTask(etask, startRunning, useMMTaskID, lTaskID, h, cb, cbArg);
1538 if (error == eCLE_Success)
1540 ResetTask(*useMMTaskID);
1543 return error;
1546 void CCryPSNMatchMaking::ResetTask(CryMatchMakingTaskID mmTaskID)
1548 STask* pTask = &m_task[mmTaskID];
1549 pTask->returnTaskID = CryMatchMakingInvalidTaskID;
1550 pTask->m_reqId = INVALID_PSN_REQUEST_ID;
1553 const char* CCryPSNMatchMaking::SSession::GetLocalUserName(uint32 localUserIndex) const
1555 if (localFlags & CRYSESSION_LOCAL_FLAG_USED)
1557 for (uint32 memberIndex = 0; memberIndex < MAX_PSN_ROOM_MEMBERS; ++memberIndex)
1559 const SRoomMember* pRoomMember = &m_members[memberIndex];
1560 if ((pRoomMember->m_valid != ePSNMI_None) && (pRoomMember->m_memberId == m_myMemberId))
1562 return pRoomMember->m_npId.handle.data;
1567 return NULL;
1570 void CCryPSNMatchMaking::SSession::Reset()
1572 PARENT::Reset();
1574 started = false;
1575 remoteConnectionProcessingToDo = false;
1576 remoteConnectionTaskID = CryMatchMakingInvalidTaskID;
1577 hostConnectionID = CryMatchMakingInvalidConnectionID;
1578 unregisteredConnectionsKicked = false;
1580 m_serverId = INVALID_PSN_SERVER_ID;
1581 m_worldId = INVALID_PSN_WORLD_ID;
1582 m_roomId = INVALID_PSN_ROOM_ID;
1583 memset(&m_sessionId, 0, sizeof(SceNpSessionId));
1585 m_myMemberId = INVALID_PSN_ROOM_MEMBER_ID;
1586 m_ownerMemberId = INVALID_PSN_ROOM_MEMBER_ID;
1589 const char* CCryPSNMatchMaking::GetConnectionName(CCryMatchMaking::SSession::SRConnection* pConnection, uint32 localUserIndex) const
1591 SSession::SRConnection* pPlatformConnection = reinterpret_cast<SSession::SRConnection*>(pConnection);
1593 if (pPlatformConnection->uid.m_uid == DEDICATED_SERVER_CONNECTION_UID)
1595 return "DedicatedServer";
1598 for (uint32 sessionIndex = 0; sessionIndex < MAX_MATCHMAKING_SESSIONS; ++sessionIndex)
1600 const SSession* pSession = &m_sessions[sessionIndex];
1602 if (pSession->localFlags & CRYSESSION_LOCAL_FLAG_USED)
1604 for (uint32 memberIndex = 0; memberIndex < MAX_PSN_ROOM_MEMBERS; ++memberIndex)
1606 const SSession::SRoomMember* pRoomMember = &pSession->m_members[memberIndex];
1607 if ((pRoomMember->m_valid != ePSNMI_None) && (pRoomMember->m_memberId == pPlatformConnection->memberId))
1609 return pRoomMember->m_npId.handle.data;
1615 return NULL;
1618 void CCryPSNMatchMaking::StartTaskRunning(CryMatchMakingTaskID mmTaskID)
1620 LOBBY_AUTO_LOCK;
1622 STask* task = &m_task[mmTaskID];
1624 if (task->used)
1626 #if ENABLE_CRYLOBBY_DEBUG_TESTS
1627 ECryLobbyError error;
1629 if (!m_lobby->DebugOKToStartTaskRunning(task->lTaskID))
1631 return;
1634 if (m_lobby->DebugGenerateError(task->lTaskID, error))
1636 UpdateTaskError(mmTaskID, error);
1637 StopTaskRunning(mmTaskID);
1639 if ((task->startedTask == eT_SessionCreate) || (task->startedTask == eT_SessionJoin))
1641 FreeSessionHandle(task->session);
1644 return;
1646 #endif
1648 task->running = true;
1650 switch (task->startedTask)
1652 case eT_SessionDelete:
1653 StartSessionDelete(mmTaskID);
1654 break;
1656 case eT_SessionUpdateSlots:
1657 case eT_SessionStart:
1658 case eT_SessionEnd:
1659 case eT_SessionRegisterUserData:
1660 StopTaskRunning(mmTaskID);
1661 break;
1663 case eT_SessionSearch:
1664 StartSessionSearch(mmTaskID);
1665 break;
1667 #if NETWORK_HOST_MIGRATION
1668 case eT_SessionMigrateHostStart:
1669 HostMigrationStartNT(mmTaskID);
1670 break;
1671 case eT_SessionMigrateHostServer:
1672 HostMigrationServerNT(mmTaskID);
1673 break;
1674 case eT_SessionSendHostHintExternal:
1675 StartSessionSendHostHintExternal(mmTaskID);
1676 break;
1677 #endif
1682 void CCryPSNMatchMaking::EndTask(CryMatchMakingTaskID mmTaskID)
1684 LOBBY_AUTO_LOCK;
1686 STask* pTask = &m_task[mmTaskID];
1688 if (pTask->used)
1690 if (m_pPSNSupport->GetNetInfo().natStatus != m_oldNatType)
1692 m_oldNatType = m_pPSNSupport->GetNetInfo().natStatus;
1694 UCryLobbyEventData eventData;
1695 SCryLobbyNatTypeData natTypeData;
1697 eventData.pNatTypeData = &natTypeData;
1699 switch (m_oldNatType)
1701 default:
1702 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_UNKNOWN:
1703 natTypeData.m_curState = eNT_Unknown;
1704 break;
1705 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_TYPE:
1706 natTypeData.m_curState = eNT_Open;
1707 break;
1708 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_TYPE2:
1709 natTypeData.m_curState = eNT_Moderate;
1710 break;
1711 case SCE_NP_MATCHING2_SIGNALING_NETINFO_NAT_STATUS_TYPE3:
1712 natTypeData.m_curState = eNT_Strict;
1713 break;
1716 if (m_lobby)
1718 m_lobby->DispatchEvent(eCLSE_NatType, eventData);
1719 m_lobby->SetNATType(natTypeData.m_curState);
1723 #if NETWORK_HOST_MIGRATION
1724 if (pTask->startedTask & HOST_MIGRATION_TASK_ID_FLAG)
1726 m_sessions[pTask->session].hostMigrationInfo.m_taskID = CryLobbyInvalidTaskID;
1728 #endif
1730 if (pTask->cb)
1732 switch (pTask->startedTask)
1734 case eT_SessionRegisterUserData:
1735 ((CryMatchmakingCallback)pTask->cb)(pTask->lTaskID, pTask->error, pTask->cbArg);
1736 break;
1738 case eT_SessionSearch:
1739 EndSessionSearch(mmTaskID);
1740 break;
1742 case eT_SessionMigrate:
1743 ((CryMatchmakingSessionCreateCallback)pTask->cb)(pTask->lTaskID, pTask->error, CreateGameSessionHandle(pTask->session, m_sessions[pTask->session].localConnection.uid), pTask->cbArg);
1744 break;
1746 case eT_SessionCreate:
1747 EndSessionCreate(mmTaskID);
1748 break;
1750 case eT_SessionQuery:
1751 EndSessionQuery(mmTaskID);
1752 break;
1754 case eT_SessionGetUsers:
1755 ((CryMatchmakingSessionGetUsersCallback)pTask->cb)(pTask->lTaskID, pTask->error, NULL, pTask->cbArg);
1756 break;
1758 case eT_SessionJoin:
1759 EndSessionJoin(mmTaskID);
1760 break;
1762 case eT_SessionSetAdvertisementData:
1763 EndSessionSetAdvertisementData(mmTaskID);
1764 break;
1766 case eT_SessionGetAdvertisementData:
1767 EndSessionGetAdvertisementData(mmTaskID);
1768 break;
1770 #if NETWORK_HOST_MIGRATION
1771 case eT_SessionSendHostHintExternal:
1772 EndSessionSendHostHintExternal(mmTaskID);
1773 break;
1774 #endif
1776 case eT_SessionUserData:
1777 case eT_SessionUpdate:
1778 case eT_SessionUpdateSlots:
1779 case eT_SessionStart:
1780 case eT_SessionEnd:
1781 case eT_SessionDelete:
1782 #if NETWORK_HOST_MIGRATION
1783 case eT_SessionMigrateHostStart:
1784 #endif
1785 ((CryMatchmakingCallback)pTask->cb)(pTask->lTaskID, pTask->error, pTask->cbArg);
1786 break;
1790 if (pTask->canceled)
1792 UpdateTaskError(mmTaskID, eCLE_InternalError);
1795 if (pTask->error != eCLE_Success)
1797 if ((pTask->startedTask == eT_SessionCreate) || (pTask->startedTask == eT_SessionJoin))
1799 if (pTask->session != CryLobbyInvalidSessionHandle)
1801 ClearSessionInfo(pTask->session);
1802 FreeSessionHandle(pTask->session);
1803 pTask->session = CryLobbyInvalidSessionHandle;
1807 NetLog("[Lobby] EndTask %d (%d) error %d", pTask->startedTask, pTask->subTask, pTask->error);
1810 // Clear PSN specific task state so that base class tasks can use this slot
1811 ResetTask(mmTaskID);
1813 FreeTask(mmTaskID);
1817 void CCryPSNMatchMaking::StopTaskRunning(CryMatchMakingTaskID mmTaskID)
1819 STask* pTask = &m_task[mmTaskID];
1821 if (pTask->used)
1823 pTask->running = false;
1824 TO_GAME_FROM_LOBBY(&CCryPSNMatchMaking::EndTask, this, mmTaskID);
1828 ECryLobbyError CCryPSNMatchMaking::CreateSessionHandle(CryLobbySessionHandle* h, bool host, uint32* users, int numUsers, uint32 flags)
1830 ECryLobbyError error = CCryMatchMaking::CreateSessionHandle(h, host, flags, numUsers);
1832 if (error == eCLE_Success)
1834 SSession* pSession = &m_sessions[*h];
1836 for (uint32 j = 0; j < numUsers; j++)
1838 pSession->localConnection.users[j] = users[j];
1841 ClearSessionInfo(*h);
1844 return error;
1847 void CCryPSNMatchMaking::Tick(CTimeValue tv)
1849 CCryMatchMaking::Tick(tv);
1851 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
1853 STask* pTask = &m_task[i];
1855 #if ENABLE_CRYLOBBY_DEBUG_TESTS
1856 if (pTask->used)
1858 if (m_lobby->DebugTickCallStartTaskRunning(pTask->lTaskID))
1860 StartTaskRunning(i);
1861 continue;
1863 if (!m_lobby->DebugOKToTickTask(pTask->lTaskID, pTask->running))
1865 continue;
1868 #endif
1870 if (pTask->used && pTask->running)
1872 if (pTask->error == eCLE_Success)
1874 switch (pTask->subTask)
1876 case eT_SessionQuery:
1877 TickSessionQuery(i);
1878 break;
1880 case eT_SessionUpdate:
1881 TickSessionUpdate(i);
1882 break;
1884 case eT_SessionUserData:
1885 TickSessionUserData(i);
1886 break;
1888 case eT_SessionRegisterUserData:
1889 case eT_SessionStart:
1890 case eT_SessionEnd:
1891 break;
1893 case eST_WaitingForJoinRoomSignalingCallback:
1895 TickSessionJoinSignaling(i);
1897 break;
1899 case eST_WaitingForCreateRoomSignalingCallback:
1901 TickSessionCreateSignaling(i);
1903 break;
1905 case eT_SessionSearch:
1906 TickSessionSearch(i);
1907 break;
1908 case eST_SessionSearchRequest:
1909 TickSessionSearchRequest(i);
1910 break;
1911 case eST_SessionSearchKickQOS:
1912 TickSessionQOSSearch(i);
1913 break;
1914 case eST_WaitingForSearchQOSRequestCallback:
1915 TickSessionWaitForQOS(i);
1916 break;
1918 case eT_SessionCreate:
1919 TickSessionCreate(i);
1920 break;
1921 case eST_SessionCreateRequest:
1922 TickSessionCreateRequest(i);
1923 break;
1925 case eT_SessionMigrate:
1926 TickSessionMigrate(i);
1927 break;
1929 case eT_SessionJoin:
1930 TickSessionJoin(i);
1931 break;
1933 case eT_SessionGetUsers:
1934 TickSessionGetUsers(i);
1935 break;
1937 case eT_SessionDelete:
1938 TickSessionDelete(i);
1939 break;
1941 case eT_SessionSetAdvertisementData:
1942 TickSessionSetAdvertisementData(i);
1943 break;
1945 case eT_SessionGetAdvertisementData:
1946 TickSessionGetAdvertisementData(i);
1947 break;
1949 #if NETWORK_HOST_MIGRATION
1950 case eT_SessionMigrateHostStart:
1951 TickHostMigrationStartNT(i);
1952 break;
1954 case eT_SessionMigrateHostServer:
1955 TickHostMigrationServerNT(i);
1956 break;
1958 case eT_SessionSendHostHintExternal:
1959 TickSessionSendHostHintExternal(i);
1960 break;
1961 #endif
1962 default:
1963 TickBaseTask(i);
1964 break;
1968 if (pTask->error != eCLE_Success)
1970 StopTaskRunning(i);
1975 UpdateVoiceUsers();
1977 const int psnShowRooms = CLobbyCVars::Get().psnShowRooms;
1978 if ((psnShowRooms != 0) && gEnv->pRenderer)
1980 static float yellow[] = { 1.0f, 1.0f, 0.4f, 1.0f };
1981 f32 ypos = 35.0f;
1983 for (uint32 i = 0; i < MAX_MATCHMAKING_SESSIONS; i++)
1985 SSession* pSession = &m_sessions[i];
1986 if (pSession->IsUsed())
1988 f32 xpos = 50.0f + (250.0f * i);
1990 // gEnv->pRenderer->Draw2dLabel(xpos, ypos, 1.5f, yellow, false, "S%d-W%d-R%lld",
1991 // pSession->m_serverId, pSession->m_worldId, pSession->m_roomId);
1997 ECryLobbyError CCryPSNMatchMaking::SessionRegisterUserData(SCrySessionUserData* data, uint32 numData, CryLobbyTaskID* taskID, CryMatchmakingCallback cb, void* cbArg)
1999 ECryLobbyError error = eCLE_Success;
2001 LOBBY_AUTO_LOCK;
2003 if (numData < MAX_MATCHMAKING_SESSION_USER_DATA)
2005 CryMatchMakingTaskID mmTaskID;
2007 error = StartTask(eT_SessionRegisterUserData, false, 0, &mmTaskID, taskID, 0, (void*)cb, cbArg);
2009 if (error == eCLE_Success)
2011 memcpy(m_registeredUserData.data, data, numData * sizeof(data[0]));
2012 m_registeredUserData.num = numData;
2014 uint32 searchableCount = 0;
2015 uint32 binBucketOffset = 0;
2016 for (uint32 a = 0; a < numData; a++)
2018 if ((m_registeredUserData.data[a].m_type == eCSUDT_Int32) && (searchableCount < SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM))
2020 m_registeredUserData.mapping[a].integerField = 1;
2021 m_registeredUserData.mapping[a].fieldOffset = searchableCount;
2023 searchableCount++;
2025 else
2027 // Either we have run out of searchable integers or the data type is not 32bit
2028 m_registeredUserData.mapping[a].integerField = 0;
2029 m_registeredUserData.mapping[a].fieldOffset = binBucketOffset;
2030 switch (m_registeredUserData.data[a].m_type)
2032 case eCSUDT_Int64:
2033 case eCSUDT_Int64NoEndianSwap:
2034 case eCSUDT_Float64:
2035 binBucketOffset += 8;
2036 break;
2037 case eCSUDT_Int32:
2038 case eCSUDT_Float32:
2039 binBucketOffset += 4;
2040 break;
2041 case eCSUDT_Int16:
2042 binBucketOffset += 2;
2043 break;
2044 case eCSUDT_Int8:
2045 binBucketOffset += 1;
2046 break;
2047 default:
2048 error = eCLE_UserDataTypeMissMatch;
2049 return error;
2051 if (binBucketOffset > (SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE * SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM))
2053 error = eCLE_OutOfSessionUserData;
2054 return error;
2059 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
2062 else
2064 error = eCLE_OutOfSessionUserData;
2067 NetLog("[Lobby] Start SessionRegisterUserData error %d", error);
2069 return error;
2072 uint32 CCryPSNMatchMaking::SortWorlds(const SCryPSNGetWorldInfoListResponse* pWorldList, SceNpMatching2WorldId* pReturnIdList, uint32 nMaxListSize, bool bIsForSearch)
2074 uint32 numWorldsSorted = 0;
2076 if (pReturnIdList && (nMaxListSize > 0))
2078 for (uint32 w = 0; w < nMaxListSize; w++)
2080 pReturnIdList[w] = INVALID_PSN_ROOM_ID;
2083 uint32 numTotalWorlds = pWorldList ? pWorldList->m_numWorlds : 0;
2084 if (pWorldList && numTotalWorlds)
2086 int forceWorld = CLobbyCVars::Get().psnForceWorld;
2087 if (forceWorld == 0)
2089 //-- For worlds metrics, we have access to two values:
2090 //-- ~ number of rooms on a world. The more rooms on a world, the better list of search results we'll get back
2091 //-- ~ players-per-room ratio. The higher the ratio, the more likely it is that the world is hosting game sessions.
2093 uint32 mostRooms = 1;
2094 f32 mostPPRRatio = 1.0f;
2095 for (uint32 i = 0; i < numTotalWorlds; i++)
2097 SCryPSNWorld& world = pWorldList->m_pWorlds[i];
2099 world.m_score = 0;
2100 world.m_sortState = SCryPSNWorld::SORT_WORLD_NONE;
2102 if (world.m_numRooms > 0)
2104 if (world.m_numRooms > mostRooms)
2106 mostRooms = world.m_numRooms;
2109 f32 fRatio = (f32)world.m_numTotalRoomMembers / (f32)world.m_numRooms;
2110 if (fRatio > mostPPRRatio)
2112 mostPPRRatio = fRatio;
2117 f32 roomsBonus = (f32)CLobbyCVars::Get().psnBestWorldNumRoomsBonus;
2118 f32 roomsPCth = (f32)mostRooms * CLobbyCVars::Get().psnBestWorldNumRoomsPivot;
2119 f32 roomsRampUp = roomsBonus / roomsPCth;
2120 f32 roomsRampDown = 0.0f;
2121 if (CLobbyCVars::Get().psnBestWorldNumRoomsPivot < 1.0f)
2123 roomsRampDown = (roomsBonus * 0.33f) / (mostRooms - roomsPCth);
2126 f32 ratioBonus = (f32)CLobbyCVars::Get().psnBestWorldPlayersPerRoomBonus;
2127 f32 ratioPCth = mostPPRRatio * CLobbyCVars::Get().psnBestWorldPlayersPerRoomPivot;
2128 f32 ratioRampUp = ratioBonus / ratioPCth;
2129 f32 ratioRampDown = 0.0f;
2130 if (CLobbyCVars::Get().psnBestWorldPlayersPerRoomPivot < 1.0f)
2132 ratioRampDown = (ratioBonus * 0.33f) / (mostPPRRatio - ratioPCth);
2135 NetLog("SortWorlds: Room Setup: %d maximum, optimal is %.02f at position %.02f", mostRooms, roomsPCth, CLobbyCVars::Get().psnBestWorldNumRoomsPivot);
2136 NetLog("SortWorlds: PPR Setup: %.04f maximum, optimal is %.04f at position %.02f", mostPPRRatio, ratioPCth, CLobbyCVars::Get().psnBestWorldPlayersPerRoomPivot);
2138 uint32 maxRooms = max(0, min(CLobbyCVars::Get().psnBestWorldMaxRooms, MAX_ROOMS_PER_WORLD));
2139 uint32 maxBonus = CLobbyCVars::Get().psnBestWorldNumRoomsBonus
2140 + CLobbyCVars::Get().psnBestWorldPlayersPerRoomBonus
2141 + CLobbyCVars::Get().psnBestWorldRandomBonus
2142 + 1;
2144 for (uint32 i = 0; i < numTotalWorlds; i++)
2146 uint32 scoreA = 0;
2147 uint32 scoreB = 0;
2148 uint32 scoreC = 0;
2149 f32 playersPerRoomRatio = 0.0f;
2151 SCryPSNWorld& world = pWorldList->m_pWorlds[i];
2153 if (world.m_numRooms > 0)
2155 //-- This could probably do with some statistical study to provide a good world score,
2156 //-- but using only the number of rooms (as we have in the past) isn't necessarily going to
2157 //-- provide a good world (it might be full of squads).
2159 f32 curNumOfRoom = (f32)world.m_numRooms;
2160 if (curNumOfRoom <= roomsPCth)
2162 scoreA = (uint32)(curNumOfRoom * roomsRampUp);
2164 else
2166 scoreA = (uint32)(roomsBonus - ((curNumOfRoom - roomsPCth) * roomsRampDown));
2169 //-- And maybe some points for players per room density, which should skew the results towards
2170 //-- worlds with bigger rooms and hopefully those are more likely to contain game sessions and not squads.
2172 playersPerRoomRatio = (f32)world.m_numTotalRoomMembers / (f32)world.m_numRooms;
2173 if (playersPerRoomRatio <= ratioPCth)
2175 scoreB = (uint32)(playersPerRoomRatio * ratioRampUp);
2177 else
2179 scoreB = (uint32)(ratioBonus - ((playersPerRoomRatio - ratioPCth) * ratioRampDown));
2182 world.m_score = scoreA + scoreB;
2185 if (bIsForSearch)
2187 //-- if sorting is for a room search, only include worlds with a score > 0
2188 if (world.m_score > 0)
2190 world.m_sortState = SCryPSNWorld::SORT_WORLD_NEEDS_SORTING;
2192 //-- We also have to make sure that at least 1 world is returned, so lets use world[0].
2193 if (i == 0)
2195 world.m_sortState = SCryPSNWorld::SORT_WORLD_NEEDS_SORTING;
2198 //-- also add a slightly random element so there's a chance that the sorted world list can change
2199 //-- (only useful if we return a subset of the sorted worlds (eg: top 3) and want some variation, otherwise it's pointless.)
2200 //-- Since we return all worlds for a search this is no longer necessary. But might be in the future.
2201 //scoreC = (cry_rand() % CNetCVars::Get().psnBestWorldRandomBonus);
2202 //world.m_score += scoreC;
2204 else
2206 //-- if sorting is for a room create, only include worlds that are not full.
2207 if (world.m_numRooms < maxRooms)
2209 world.m_sortState = SCryPSNWorld::SORT_WORLD_NEEDS_SORTING;
2213 NetLog("SortWorlds: World %02d : ID %d: Score = %d + %d + %d = %d (%d rooms ~ %.2f PPR)", i + 1, world.m_worldId,
2214 scoreA, scoreB, scoreC, world.m_score, world.m_numRooms, playersPerRoomRatio);
2217 //-- We have a set of valid worlds to sort now, so we just have to add them to the return list in the correct order.
2218 //-- It's a pretty bad selection sort algorithm, but it doesn't need to be hugely performance critical.
2219 bool bSorting = true;
2220 while (bSorting)
2222 SCryPSNWorld* pBestWorld = NULL;
2223 uint32 highestWorldScore = 0;
2224 uint32 lowestWorldScore = maxBonus;
2226 for (uint32 l = 0; l < numTotalWorlds; l++)
2228 SCryPSNWorld* pWorld = &pWorldList->m_pWorlds[l];
2230 if (pWorld->m_sortState == SCryPSNWorld::SORT_WORLD_NEEDS_SORTING)
2232 if (bIsForSearch)
2234 // search returns the highest scoring worlds first
2235 if (pWorld->m_score >= highestWorldScore)
2237 highestWorldScore = pWorld->m_score;
2238 pBestWorld = pWorld;
2241 else
2243 // create returns the lowest scoring worlds first.
2244 // I'm not sure this is really what we want...
2245 if (pWorld->m_score < lowestWorldScore)
2247 lowestWorldScore = pWorld->m_score;
2248 pBestWorld = pWorld;
2254 if (pBestWorld)
2256 pReturnIdList[numWorldsSorted] = pBestWorld->m_worldId;
2257 pBestWorld->m_sortState = SCryPSNWorld::SORT_WORLD_SORTED;
2259 numWorldsSorted++;
2260 if (numWorldsSorted >= nMaxListSize)
2262 bSorting = false;
2265 NetLog("SortWorlds: Sorted %02d : ID %d: Score = %d", numWorldsSorted, pBestWorld->m_worldId, pBestWorld->m_score);
2267 else
2269 //-- No more worlds to add to sorted list
2270 bSorting = false;
2274 else
2276 if ((forceWorld >= 1) && (forceWorld <= numTotalWorlds))
2278 pReturnIdList[0] = pWorldList->m_pWorlds[forceWorld - 1].m_worldId;
2280 else
2282 pReturnIdList[0] = pWorldList->m_pWorlds[0].m_worldId;
2284 numWorldsSorted = 1;
2289 return numWorldsSorted;
2292 void CCryPSNMatchMaking::ProcessExternalRoomData(const SCryPSNRoomDataExternal& curRoom, SCrySessionSearchResult& result, SCrySessionUserData userData[MAX_MATCHMAKING_SESSION_USER_DATA])
2294 SCryPSNSessionID* pRoomInfo = new SCryPSNSessionID;
2296 pRoomInfo->m_sessionInfo.m_roomId = curRoom.m_roomId;
2297 pRoomInfo->m_sessionInfo.m_worldId = curRoom.m_worldId;
2298 pRoomInfo->m_sessionInfo.m_serverId = curRoom.m_serverId;
2299 pRoomInfo->m_sessionInfo.m_gameType = 0;
2300 memset(&pRoomInfo->m_sessionId, 0, sizeof(pRoomInfo->m_sessionId));
2301 pRoomInfo->m_fromInvite = false;
2303 result.m_id = pRoomInfo;
2305 result.m_numFilledSlots = curRoom.m_numPublicSlots - curRoom.m_numOpenPublicSlots;
2306 result.m_numFriends = 0;
2307 result.m_flags = 0;
2309 result.m_data.m_ranked = false;
2310 result.m_data.m_name[0] = 0;
2311 result.m_data.m_data = userData;
2312 result.m_data.m_numData = 0;
2314 result.m_data.m_numPublicSlots = curRoom.m_numPublicSlots;
2315 result.m_data.m_numPrivateSlots = curRoom.m_numPrivateSlots;
2317 for (uint32 k = 0; k < SCE_NP_ONLINEID_MAX_LENGTH; k++)
2319 result.m_data.m_name[k] = (char)curRoom.m_owner.handle.data[k];
2321 result.m_data.m_name[SCE_NP_ONLINEID_MAX_LENGTH] = 0;
2323 for (int a = 0; a < curRoom.m_numSearchableUIntAttributes; a++)
2325 for (int b = 0; b < m_registeredUserData.num; b++)
2327 if (m_registeredUserData.mapping[b].integerField)
2329 if (curRoom.m_searchableUIntAttributes[a].m_id == m_registeredUserData.mapping[b].fieldOffset + SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID)
2331 result.m_data.m_data[result.m_data.m_numData].m_id = m_registeredUserData.data[b].m_id;
2332 result.m_data.m_data[result.m_data.m_numData].m_type = m_registeredUserData.data[b].m_type;
2333 result.m_data.m_data[result.m_data.m_numData].m_int32 = curRoom.m_searchableUIntAttributes[a].m_num;
2335 result.m_data.m_numData++;
2336 break;
2342 char binAttrExternalData[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE * SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM];
2344 for (int a = 0; a < curRoom.m_numBinAttributes; a++)
2346 memcpy(&binAttrExternalData[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE * a], curRoom.m_binAttributes[a].m_data, curRoom.m_binAttributes[a].m_dataSize);
2349 for (int b = 0; b < m_registeredUserData.num; b++)
2351 if (!m_registeredUserData.mapping[b].integerField)
2353 result.m_data.m_data[result.m_data.m_numData].m_id = m_registeredUserData.data[b].m_id;
2354 result.m_data.m_data[result.m_data.m_numData].m_type = m_registeredUserData.data[b].m_type;
2356 void* dPtr;
2357 switch (result.m_data.m_data[result.m_data.m_numData].m_type)
2359 case eCSUDT_Int64:
2360 case eCSUDT_Int64NoEndianSwap:
2361 case eCSUDT_Float64:
2362 dPtr = (void*)&result.m_data.m_data[result.m_data.m_numData].m_int64;
2363 memcpy(dPtr, &binAttrExternalData[m_registeredUserData.mapping[b].fieldOffset], sizeof(result.m_data.m_data[result.m_data.m_numData].m_int64));
2364 break;
2365 case eCSUDT_Int32:
2366 case eCSUDT_Float32:
2367 dPtr = (void*)&result.m_data.m_data[result.m_data.m_numData].m_int32;
2368 memcpy(dPtr, &binAttrExternalData[m_registeredUserData.mapping[b].fieldOffset], sizeof(result.m_data.m_data[result.m_data.m_numData].m_int32));
2369 break;
2370 case eCSUDT_Int16:
2371 dPtr = (void*)&result.m_data.m_data[result.m_data.m_numData].m_int16;
2372 memcpy(dPtr, &binAttrExternalData[m_registeredUserData.mapping[b].fieldOffset], sizeof(result.m_data.m_data[result.m_data.m_numData].m_int16));
2373 break;
2374 case eCSUDT_Int8:
2375 dPtr = (void*)&result.m_data.m_data[result.m_data.m_numData].m_int8;
2376 memcpy(dPtr, &binAttrExternalData[m_registeredUserData.mapping[b].fieldOffset], sizeof(result.m_data.m_data[result.m_data.m_numData].m_int8));
2377 break;
2379 result.m_data.m_numData++;
2384 void CCryPSNMatchMaking::BuildUserSessionParams(SSession* pSession, SCrySessionUserData* pData, uint32 numData,
2385 SceNpMatching2BinAttr binAttrExternal[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM],
2386 SceNpMatching2IntAttr intAttrExternal[SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM],
2387 char binAttrExternalData[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE * SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM])
2389 // Setup our advertiser data
2390 for (int a = 0; a < SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM; a++)
2392 binAttrExternal[a].id = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID + a;
2393 binAttrExternal[a].ptr = &binAttrExternalData[SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE * a];
2394 binAttrExternal[a].size = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE; // should really shrink these to avoid sending unused data
2397 for (int a = 0; a < SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM; a++)
2399 intAttrExternal[a].id = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID + a;
2402 // Build user data into psn format
2403 if (pSession->IsUsed())
2405 for (uint32 i = 0; i < numData; i++)
2407 uint32 j;
2409 for (j = 0; j < m_registeredUserData.num; j++)
2411 if (pData[i].m_id == m_registeredUserData.data[j].m_id)
2413 if (pData[i].m_type == m_registeredUserData.data[j].m_type)
2415 if (m_registeredUserData.mapping[j].integerField)
2417 intAttrExternal[m_registeredUserData.mapping[j].fieldOffset].num = pData[i].m_int32;
2419 else
2421 void* dPtr;
2422 switch (pData[i].m_type)
2424 case eCSUDT_Int64:
2425 case eCSUDT_Int64NoEndianSwap:
2426 case eCSUDT_Float64:
2427 dPtr = (void*)&pData[i].m_int64;
2428 memcpy(&binAttrExternalData[m_registeredUserData.mapping[j].fieldOffset], dPtr, sizeof(pData[i].m_int64));
2429 break;
2430 case eCSUDT_Int32:
2431 case eCSUDT_Float32:
2432 dPtr = (void*)&pData[i].m_int32;
2433 memcpy(&binAttrExternalData[m_registeredUserData.mapping[j].fieldOffset], dPtr, sizeof(pData[i].m_int32));
2434 break;
2435 case eCSUDT_Int16:
2436 dPtr = (void*)&pData[i].m_int16;
2437 memcpy(&binAttrExternalData[m_registeredUserData.mapping[j].fieldOffset], dPtr, sizeof(pData[i].m_int16));
2438 break;
2439 case eCSUDT_Int8:
2440 dPtr = (void*)&pData[i].m_int8;
2441 memcpy(&binAttrExternalData[m_registeredUserData.mapping[j].fieldOffset], dPtr, sizeof(pData[i].m_int8));
2442 break;
2452 // SESSION CREATE -----------------------------------------------------------------------------------------
2454 ECryLobbyError CCryPSNMatchMaking::SessionCreate(uint32* users, int numUsers, uint32 flags, SCrySessionData* data, CryLobbyTaskID* taskID, CryMatchmakingSessionCreateCallback cb, void* cbArg)
2456 LOBBY_AUTO_LOCK;
2458 CryLobbySessionHandle h;
2459 ECryLobbyError error = CreateSessionHandle(&h, true, users, numUsers, flags);
2461 if (error == eCLE_Success)
2463 CryMatchMakingTaskID mmTaskID;
2465 error = StartTask(eT_SessionCreate, false, users[0], &mmTaskID, taskID, h, (void*)cb, cbArg);
2467 if (error == eCLE_Success)
2469 SSession* pSession = &m_sessions[h];
2471 pSession->m_flags = SCE_NP_MATCHING2_ROOM_FLAG_ATTR_OWNER_AUTO_GRANT; // Auto migrate
2473 if ((flags & CRYSESSION_CREATE_FLAG_SEARCHABLE) == 0)
2475 pSession->m_flags |= SCE_NP_MATCHING2_ROOM_FLAG_ATTR_HIDDEN;
2478 if (data->m_ranked)
2480 pSession->m_flags |= 0; // TODO.. implement ranked rooms
2481 pSession->m_gameType = 0;
2483 else
2485 pSession->m_gameType = 0;
2488 pSession->m_gameMode = 0;
2489 pSession->m_numPublicSlots = data->m_numPublicSlots;
2490 pSession->m_numPrivateSlots = data->m_numPrivateSlots;
2492 NetLog("[Lobby] Created local connection " PRFORMAT_SH " " PRFORMAT_UID, PRARG_SH(h), PRARG_UID(pSession->localConnection.uid));
2494 for (uint32 i = 0; i < numUsers; i++)
2496 pSession->localConnection.privateSlot[i] = TRUE;
2499 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_CREATE_PARAMS_SLOT, data, 1, sizeof(SCrySessionData));
2501 if (error == eCLE_Success)
2503 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_CREATE_DATA_SLOT, data->m_data, data->m_numData, data->m_numData * sizeof(data->m_data[0]));
2505 if (error == eCLE_Success)
2507 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT, NULL, 1, sizeof(SCreateParamData));
2509 if (error == eCLE_Success)
2511 // This next alloc is a doozy - 165KB-ish
2512 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_WEBAPI_CREATE_SLOT, NULL, 1, sizeof(SCryPSNOrbisWebApiCreateSessionInput));
2513 if (error == eCLE_Success)
2515 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
2517 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
2523 if (error != eCLE_Success)
2525 FreeTask(mmTaskID);
2526 FreeSessionHandle(h);
2529 else
2531 FreeSessionHandle(h);
2535 NetLog("[Lobby] Start SessionCreate error %d", error);
2537 return error;
2540 void CCryPSNMatchMaking::TickSessionCreate(CryMatchMakingTaskID mmTaskID)
2542 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
2543 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
2545 STask* pTask = &m_task[mmTaskID];
2547 //-- get the world list
2548 StartSubTask(eST_WaitingForCreateRoomWorldInfo, mmTaskID);
2550 SceNpMatching2GetWorldInfoListRequest reqParam;
2551 memset(&reqParam, 0, sizeof(reqParam));
2552 reqParam.serverId = m_pPSNSupport->GetServerInfo()->server.serverId;
2554 int ret = sceNpMatching2GetWorldInfoList(m_pPSNSupport->GetMatchmakingContextId(), &reqParam, NULL, &pTask->m_reqId);
2555 if (ret == PSN_OK)
2557 //-- Waiting for callback
2559 else
2561 NetLog("sceNpMatching2GetWorldInfoList : error %08X", ret);
2562 if (!m_pPSNSupport->HandlePSNError(ret))
2564 UpdateTaskError(mmTaskID, eCLE_WorldNotDefined);
2570 bool CCryPSNMatchMaking::EventRequestResponse_GetWorldInfoListForCreate(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
2572 assert(pTask->subTask == eST_WaitingForCreateRoomWorldInfo);
2573 assert(data.m_requestEvent.m_event == REQUEST_EVENT_GET_WORLD_INFO_LIST);
2574 assert(data.m_requestEvent.m_dataSize == sizeof(SCryPSNGetWorldInfoListResponse));
2576 if ((data.m_requestEvent.m_error == 0) &&
2577 (data.m_requestEvent.m_dataHdl != TMemInvalidHdl) &&
2578 (data.m_requestEvent.m_dataSize == sizeof(SCryPSNGetWorldInfoListResponse)))
2580 SCreateParamData* pCreateParams = (SCreateParamData*)_this->m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT]);
2581 if (pCreateParams)
2583 memset(pCreateParams, 0, sizeof(SCreateParamData));
2585 const SCryPSNGetWorldInfoListResponse* pWorldList = (SCryPSNGetWorldInfoListResponse*)_this->m_lobby->MemGetPtr(data.m_requestEvent.m_dataHdl);
2587 uint32 listSize = SortWorlds(pWorldList, &pCreateParams->m_createRequest.worldId, 1, false);
2588 if ((listSize > 0) && (pCreateParams->m_createRequest.worldId != INVALID_PSN_WORLD_ID))
2590 _this->StartSubTask(eST_SessionCreateRequest, taskId);
2592 else
2594 _this->UpdateTaskError(taskId, eCLE_WorldNotDefined);
2597 else
2599 _this->UpdateTaskError(taskId, eCLE_OutOfMemory);
2602 return true;
2604 else
2606 return false;
2610 // At present there are only 8 possible searchable integer values (so we need to be careful with which attributes use them.
2611 // For now I have chucked all the data into the 2 binary attributes (256 bytes each). If I run out, i`ll panic later.
2612 void CCryPSNMatchMaking::TickSessionCreateRequest(CryMatchMakingTaskID mmTaskID)
2614 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
2615 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
2617 STask* pTask = &m_task[mmTaskID];
2619 if (pTask->params[PSN_MATCHMAKING_CREATE_PARAMS_SLOT] != TMemInvalidHdl)
2621 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT] != TMemInvalidHdl)
2623 SCrySessionData* pData = (SCrySessionData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_CREATE_PARAMS_SLOT]);
2624 if (pTask->params[PSN_MATCHMAKING_CREATE_DATA_SLOT] != TMemInvalidHdl)
2626 pData->m_data = (SCrySessionUserData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_CREATE_DATA_SLOT]);
2628 else
2630 pData->m_data = NULL;
2633 SCreateParamData* pCreateParams = (SCreateParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT]);
2634 SSession* pSession = &m_sessions[pTask->session];
2636 BuildUserSessionParams(pSession, pData->m_data, pData->m_numData, pCreateParams->m_binAttrExternal, pCreateParams->m_intAttrExternal, pCreateParams->m_binAttrExternalData);
2638 // Internal data defaults
2639 for (int32 index = 0; index < SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_NUM; ++index)
2641 pCreateParams->m_binAttrInternal[index].id = SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_1_ID + index;
2642 pCreateParams->m_binAttrInternal[index].ptr = &pCreateParams->m_binAttrInternalData[SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_MAX_SIZE * index];
2643 pCreateParams->m_binAttrInternal[index].size = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_MAX_SIZE; // should really shrink these to avoid sending unused data
2646 // Build internal data
2647 const int numInternalData = 1;
2648 uint16 sessionCreateGameFlags = (pSession->createFlags & CRYSESSION_CREATE_FLAG_GAME_MASK) >> CRYSESSION_CREATE_FLAG_GAME_FLAGS_SHIFT;
2649 memcpy((void*)pCreateParams->m_binAttrInternal[0].ptr, &sessionCreateGameFlags, sizeof(sessionCreateGameFlags));
2650 pCreateParams->m_binAttrInternal[0].size = sizeof(sessionCreateGameFlags);
2652 SceNpMatching2SignalingOptParam sigParams;
2653 sigParams.type = SCE_NP_MATCHING2_SIGNALING_TYPE_MESH;
2654 sigParams.flag = 0;
2655 sigParams.hubMemberId = 0;
2657 pCreateParams->m_createRequest.maxSlot = pSession->m_numPrivateSlots + pSession->m_numPublicSlots;
2658 pCreateParams->m_createRequest.flagAttr = pSession->m_flags;
2659 pCreateParams->m_createRequest.roomPassword = NULL;
2660 pCreateParams->m_createRequest.groupConfig = NULL;
2661 pCreateParams->m_createRequest.groupConfigNum = 0;
2662 pCreateParams->m_createRequest.passwordSlotMask = NULL;
2663 pCreateParams->m_createRequest.allowedUser = NULL;
2664 pCreateParams->m_createRequest.allowedUserNum = 0;
2665 pCreateParams->m_createRequest.blockedUser = NULL;
2666 pCreateParams->m_createRequest.blockedUserNum = 0;
2667 pCreateParams->m_createRequest.sigOptParam = &sigParams;
2668 pCreateParams->m_createRequest.roomBinAttrInternal = pCreateParams->m_binAttrInternal;
2669 pCreateParams->m_createRequest.roomBinAttrInternalNum = numInternalData;
2670 pCreateParams->m_createRequest.roomBinAttrExternal = pCreateParams->m_binAttrExternal;
2671 pCreateParams->m_createRequest.roomBinAttrExternalNum = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM;
2672 pCreateParams->m_createRequest.roomSearchableBinAttrExternal = NULL;
2673 pCreateParams->m_createRequest.roomSearchableBinAttrExternalNum = 0;
2674 pCreateParams->m_createRequest.roomSearchableIntAttrExternal = pCreateParams->m_intAttrExternal;
2675 pCreateParams->m_createRequest.roomSearchableIntAttrExternalNum = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM;
2676 pCreateParams->m_createRequest.joinRoomGroupLabel = NULL;
2677 pCreateParams->m_createRequest.roomMemberBinAttrInternal = NULL;
2678 pCreateParams->m_createRequest.roomMemberBinAttrInternalNum = 0;
2679 pCreateParams->m_createRequest.teamId = 0;
2681 StartSubTask(eST_WaitingForCreateRoomRequestCallback, mmTaskID);
2683 int ret = sceNpMatching2CreateJoinRoom(m_pPSNSupport->GetMatchmakingContextId(), &pCreateParams->m_createRequest, NULL, &pTask->m_reqId);
2684 if (ret == PSN_OK)
2686 //-- waiting for callback
2688 else
2690 NetLog("sceNpMatching2CreateJoinRoom : error %08X", ret);
2691 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
2692 //-- otherwise, we have to update the task error ourself.
2693 if (!m_pPSNSupport->HandlePSNError(ret))
2695 UpdateTaskError(mmTaskID, eCLE_InternalError);
2699 else
2701 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
2704 else
2706 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
2711 bool CCryPSNMatchMaking::EventRequestResponse_CreateRoom(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
2713 // sanity
2714 assert(pTask->subTask == eST_WaitingForCreateRoomRequestCallback);
2715 assert(data.m_requestEvent.m_event == REQUEST_EVENT_CREATE_JOIN_ROOM);
2716 assert(data.m_requestEvent.m_dataHdl != TMemInvalidHdl);
2717 assert(data.m_requestEvent.m_dataSize == sizeof(SCryPSNCreateJoinRoomResponse));
2719 if ((data.m_requestEvent.m_error == 0) &&
2720 (data.m_requestEvent.m_dataHdl != TMemInvalidHdl) &&
2721 (data.m_requestEvent.m_dataSize == sizeof(SCryPSNCreateJoinRoomResponse)))
2723 const SCryPSNCreateJoinRoomResponse* pCreateResponse = (SCryPSNCreateJoinRoomResponse*)_this->m_pPSNSupport->GetLobby()->MemGetPtr(data.m_requestEvent.m_dataHdl);
2725 if (pTask->session != CryLobbyInvalidSessionHandle)
2727 SSession* pSession = &_this->m_sessions[pTask->session];
2728 if (pSession->IsUsed())
2730 pSession->m_roomId = pCreateResponse->m_roomInfo.m_roomId;
2731 pSession->m_worldId = pCreateResponse->m_roomInfo.m_worldId;
2732 pSession->m_serverId = pCreateResponse->m_roomInfo.m_serverId;
2734 if (!pTask->canceled)
2736 _this->AddInitialRoomMembers(pTask->session, pCreateResponse->m_roomMembers);
2737 _this->StartSubTask(eST_WaitingForCreateRoomSignalingCallback, taskId);
2739 else
2741 _this->UpdateTaskError(taskId, eCLE_IllegalSessionJoin);
2744 else
2746 _this->UpdateTaskError(taskId, eCLE_InternalError);
2749 else
2751 _this->UpdateTaskError(taskId, eCLE_InternalError);
2754 return true;
2756 else
2758 return false;
2762 void CCryPSNMatchMaking::TickSessionCreateSignaling(CryMatchMakingTaskID mmTaskID)
2764 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
2765 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
2767 STask* pTask = &m_task[mmTaskID];
2769 UpdateSignaling(mmTaskID);
2771 switch (CheckSignaling(mmTaskID))
2773 case ePSNCS_None:
2775 //-- This is bad, means there is no room owner!
2776 UpdateTaskError(mmTaskID, eCLE_InvalidParam);
2778 break;
2780 case ePSNCS_Active:
2782 assert(pTask->subTask == eST_WaitingForCreateRoomSignalingCallback);
2784 if (pTask->session != CryLobbyInvalidSessionHandle)
2786 SSession* pSession = &m_sessions[pTask->session];
2787 if (pSession->IsUsed())
2789 if (!pTask->canceled)
2791 if (pSession->createFlags & CRYSESSION_CREATE_FLAG_INVITABLE)
2793 SCrySessionData* pSessionData = (SCrySessionData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_CREATE_PARAMS_SLOT]);
2794 SCreateParamData* pCreateParams = (SCreateParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_CREATE_REQUEST_SLOT]);
2795 SCryPSNOrbisWebApiCreateSessionInput* pWebApiCreateParams = (SCryPSNOrbisWebApiCreateSessionInput*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_WEBAPI_CREATE_SLOT]);
2796 if (pSessionData && pCreateParams && pWebApiCreateParams)
2798 StartSubTask(eST_WaitingForCreateRoomWebApiCallback, mmTaskID);
2800 memset(pWebApiCreateParams, 0, sizeof(SCryPSNOrbisWebApiCreateSessionInput));
2802 // Some of the SCryLobbySessionAdvertisement we can fill in now.
2803 SCryLobbySessionAdvertisement& advertisement = pWebApiCreateParams->advertisement;
2805 advertisement.m_numSlots = pSessionData->m_numPublicSlots + pSessionData->m_numPrivateSlots;
2806 advertisement.m_bIsPrivate = false;
2807 advertisement.m_bIsEditableByAll = true;
2808 advertisement.m_pData = pWebApiCreateParams->data;
2810 if (pTask->session != CryLobbyInvalidSessionHandle)
2812 // default session advertisement data should be set to the matching2 room info if available
2813 SSession* pSession = &m_sessions[pTask->session];
2814 SSynchronisedSessionID* pSessionInfo = (SSynchronisedSessionID*)advertisement.m_pData;
2816 pSessionInfo->m_serverId = pSession->m_serverId;
2817 pSessionInfo->m_worldId = pSession->m_worldId;
2818 pSessionInfo->m_roomId = pSession->m_roomId;
2819 pSessionInfo->m_gameType = pSession->m_gameType;
2820 advertisement.m_sizeofData = sizeof(SSynchronisedSessionID);
2822 else
2824 // otherwise just set the session advertisement data to an empty chunk of maximum size
2825 advertisement.m_sizeofData = CRY_WEBAPI_CREATESESSION_LINKDATA_MAX_SIZE;
2828 // The rest needs filling in and/or modifying via configuration callback to the game.
2829 SConfigurationParams neededInfo = {
2830 CLCC_PSN_CREATE_SESSION_ADVERTISEMENT, { NULL }
2832 neededInfo.m_pData = (void*)&pWebApiCreateParams->advertisement;
2833 m_lobby->GetConfigurationInformation(&neededInfo, 1);
2835 // And now we should have a completed SCryLobbySessionAdvertisement structure available to us. We'll be using this in CCryPSNOrbisWebApiThread::CreateSession later on.
2836 pCreateParams->m_createJobId = m_pPSNSupport->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::CreateSession, pTask->params[PSN_MATCHMAKING_WEBAPI_CREATE_SLOT]);
2837 if (pCreateParams->m_createJobId == INVALID_WEBAPI_JOB_ID)
2839 // failed
2840 UpdateTaskError(mmTaskID, eCLE_InternalError);
2843 else
2845 UpdateTaskError(mmTaskID, eCLE_InternalError);
2848 else
2850 // Session is not invitable, so we don't need the session Id.
2851 UpdateTaskError(mmTaskID, eCLE_Success);
2852 StopTaskRunning(mmTaskID);
2855 else
2857 // cancelled
2858 UpdateTaskError(mmTaskID, eCLE_IllegalSessionJoin);
2861 else
2863 UpdateTaskError(mmTaskID, eCLE_InternalError);
2866 else
2868 UpdateTaskError(mmTaskID, eCLE_InternalError);
2871 break;
2873 case ePSNCS_Dead:
2875 assert(pTask->subTask == eST_WaitingForCreateRoomSignalingCallback);
2877 UpdateTaskError(mmTaskID, eCLE_ConnectionFailed);
2879 break;
2884 void CCryPSNMatchMaking::EventWebApiCreateSession(CryMatchMakingTaskID mmTaskID, SCryPSNSupportCallbackEventData& data)
2886 STask* pTask = &m_task[mmTaskID];
2888 if (pTask->session != CryLobbyInvalidSessionHandle)
2890 SSession* pSession = &m_sessions[pTask->session];
2892 memset(&pSession->m_sessionId, 0, sizeof(SceNpSessionId));
2894 if (data.m_webApiEvent.m_error == PSN_OK)
2896 if (data.m_webApiEvent.m_pResponseBody)
2898 if (data.m_webApiEvent.m_pResponseBody->eType == SCryPSNWebApiResponseBody::E_JSON)
2900 // parse json to get session ID
2901 // CCryPSNWebApiJobController::PrintResponseJSONTree(data.m_webApiEvent.m_pResponseBody);
2902 const sce::Json::Value& val = data.m_webApiEvent.m_pResponseBody->jsonTreeRoot["sessionId"];
2903 if (val.getType() == sce::Json::kValueTypeString)
2905 strncpy((char*)&pSession->m_sessionId, val.toString().c_str(), sizeof(pSession->m_sessionId.data));
2906 pSession->m_sessionId.term = 0;
2908 // Completed successfully
2909 UpdateTaskError(mmTaskID, eCLE_Success);
2910 StopTaskRunning(mmTaskID);
2912 return;
2918 // something went wrong
2919 UpdateTaskError(mmTaskID, eCLE_InternalError);
2920 StopTaskRunning(mmTaskID);
2923 // otherwise something went wrong!
2924 UpdateTaskError(mmTaskID, eCLE_InternalError);
2925 StopTaskRunning(mmTaskID);
2928 void CCryPSNMatchMaking::EndSessionCreate(CryMatchMakingTaskID mmTaskID)
2930 STask* pTask = &m_task[mmTaskID];
2931 SSession* pSession = &m_sessions[pTask->session];
2933 if (pTask->error == eCLE_Success)
2935 SCryMatchMakingConnectionUID matchingUID;
2936 matchingUID.m_uid = pSession->m_myMemberId;
2937 matchingUID.m_sid = pSession->m_roomId;
2939 pSession->localConnection.uid = matchingUID;
2940 pSession->localConnection.pingToServer = CRYLOBBY_INVALID_PING;
2941 pSession->localConnection.used = true;
2942 pSession->hostConnectionID = CryMatchMakingInvalidConnectionID;
2944 else
2946 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
2949 ((CryMatchmakingSessionCreateCallback)pTask->cb)(pTask->lTaskID, pTask->error, CreateGameSessionHandle(pTask->session, pSession->localConnection.uid), pTask->cbArg);
2951 if (pTask->error == eCLE_Success)
2953 InitialUserDataEvent(pTask->session);
2957 // END SESSON CREATE ---------------------------------------------------------------------------------------
2959 ECryLobbyError CCryPSNMatchMaking::SessionMigrate(CrySessionHandle gh, uint32* pUsers, int numUsers, uint32 flags, SCrySessionData* pData, CryLobbyTaskID* pTaskID, CryMatchmakingSessionCreateCallback pCB, void* pCBArg)
2961 ECryLobbyError error = eCLE_Success;
2963 LOBBY_AUTO_LOCK;
2965 // Because we simply want to re-use the session that is already available, we don't need to do much here
2967 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
2969 if ((h < MAX_MATCHMAKING_SESSIONS) && (m_sessions[h].localFlags & CRYSESSION_LOCAL_FLAG_USED))
2971 SSession* pSession = &m_sessions[h];
2972 CryMatchMakingTaskID mmTaskID;
2974 error = StartTask(eT_SessionMigrate, false, pSession->localConnection.users[0], &mmTaskID, pTaskID, h, (void*)pCB, pCBArg);
2976 if (error == eCLE_Success)
2978 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
2981 else
2983 error = eCLE_InvalidSession;
2986 NetLog("[Lobby] Start SessionMigrate error %d", error);
2988 return error;
2991 void CCryPSNMatchMaking::TickSessionMigrate(CryMatchMakingTaskID mmTaskID)
2993 UpdateTaskError(mmTaskID, eCLE_Success);
2994 StopTaskRunning(mmTaskID);
2997 ECryLobbyError CCryPSNMatchMaking::SessionUpdate(CrySessionHandle gh, SCrySessionUserData* pData, uint32 numData, CryLobbyTaskID* pTaskID, CryMatchmakingCallback pCB, void* pCBArg)
2999 ECryLobbyError error = eCLE_Success;
3001 LOBBY_AUTO_LOCK;
3003 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
3005 if ((h < MAX_MATCHMAKING_SESSIONS) && (m_sessions[h].localFlags & CRYSESSION_LOCAL_FLAG_USED))
3007 SSession* session = &m_sessions[h];
3009 if (session->localFlags & CRYSESSION_LOCAL_FLAG_HOST)
3011 CryMatchMakingTaskID mmTaskID;
3013 error = StartTask(eT_SessionUpdate, false, session->localConnection.users[0], &mmTaskID, pTaskID, h, (void*)pCB, pCBArg);
3015 if (error == eCLE_Success)
3017 STask* task = &m_task[mmTaskID];
3019 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_UPDATE_DATA_SLOT, pData, numData, numData * sizeof(pData[0]));
3021 if (error == eCLE_Success)
3023 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT, NULL, 1, sizeof(SUpdateParamData));
3024 if (error == eCLE_Success)
3026 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3028 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3030 else
3032 FreeTask(mmTaskID);
3035 else
3037 FreeTask(mmTaskID);
3041 else
3043 error = eCLE_InvalidRequest;
3046 else
3048 error = eCLE_InvalidSession;
3051 NetLog("[Lobby] Start SessionUpdate error %d", error);
3053 return error;
3056 void CCryPSNMatchMaking::TickSessionUpdate(CryMatchMakingTaskID mmTaskID)
3058 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3059 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
3061 STask* pTask = &m_task[mmTaskID];
3063 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT] != TMemInvalidHdl)
3065 SUpdateParamData* pUpdateParams = (SUpdateParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_UPDATE_REQUEST_SLOT]);
3066 SCrySessionUserData* pData = (SCrySessionUserData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_UPDATE_DATA_SLOT]);
3067 SSession* pSession = &m_sessions[pTask->session];
3069 memset(pUpdateParams, 0, sizeof(SUpdateParamData));
3071 BuildUserSessionParams(pSession, pData, pTask->numParams[0], pUpdateParams->m_binAttrExternal, pUpdateParams->m_intAttrExternal, pUpdateParams->m_binAttrExternalData);
3073 pUpdateParams->m_updateRequest.roomId = pSession->m_roomId;
3075 pUpdateParams->m_updateRequest.roomSearchableIntAttrExternal = pUpdateParams->m_intAttrExternal;
3076 pUpdateParams->m_updateRequest.roomSearchableBinAttrExternal = NULL;
3077 pUpdateParams->m_updateRequest.roomBinAttrExternal = pUpdateParams->m_binAttrExternal;
3079 pUpdateParams->m_updateRequest.roomSearchableBinAttrExternalNum = 0;
3080 pUpdateParams->m_updateRequest.roomSearchableIntAttrExternalNum = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM;
3081 pUpdateParams->m_updateRequest.roomBinAttrExternalNum = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_NUM;
3083 StartSubTask(eST_WaitingForUpdateRoomRequestCallback, mmTaskID);
3085 int ret = sceNpMatching2SetRoomDataExternal(m_pPSNSupport->GetMatchmakingContextId(), &pUpdateParams->m_updateRequest, NULL, &pTask->m_reqId);
3086 if (ret == PSN_OK)
3088 //-- Waiting for callback
3090 else
3092 NetLog("sceNpMatching2SetRoomDataExternal : error %08X", ret);
3093 if (!m_pPSNSupport->HandlePSNError(ret))
3095 UpdateTaskError(mmTaskID, eCLE_InternalError);
3099 else
3101 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
3106 bool CCryPSNMatchMaking::EventRequestResponse_SetRoomDataExternal(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
3108 // sanity
3109 assert(pTask->subTask == eST_WaitingForUpdateRoomRequestCallback);
3110 assert(data.m_requestEvent.m_event == REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL);
3111 assert(data.m_requestEvent.m_dataSize == 0);
3113 if (data.m_requestEvent.m_error == 0)
3115 _this->UpdateTaskError(taskId, eCLE_Success);
3116 _this->StopTaskRunning(taskId);
3118 return true;
3120 else
3122 // return false to let the default error handler work
3123 return false;
3127 // END SESSION UPDATE ------------------------------------------------------------------------
3129 ECryLobbyError CCryPSNMatchMaking::SessionUpdateSlots(CrySessionHandle gh, uint32 numPublic, uint32 numPrivate, CryLobbyTaskID* pTaskID, CryMatchmakingCallback pCB, void* pCBArg)
3131 ECryLobbyError error = eCLE_Success;
3133 LOBBY_AUTO_LOCK;
3135 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
3137 if ((h < MAX_MATCHMAKING_SESSIONS) && (m_sessions[h].localFlags & CRYSESSION_LOCAL_FLAG_USED))
3139 CryMatchMakingTaskID tid;
3141 error = StartTask(eT_SessionUpdateSlots, false, m_sessions[h].localConnection.users[0], &tid, pTaskID, h, (void*)pCB, pCBArg);
3143 if (error == eCLE_Success)
3145 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, tid);
3148 else
3150 error = eCLE_InvalidSession;
3153 NetLog("[Lobby] Start SessionUpdateSlots return %d", error);
3155 return error;
3158 #if NETWORK_HOST_MIGRATION
3159 ECryLobbyError CCryPSNMatchMaking::SendHostHintExternal(CryLobbySessionHandle h)
3161 ECryLobbyError error = eCLE_Success;
3162 LOBBY_AUTO_LOCK;
3164 if (net_enable_psn_hinting)
3166 if ((h < MAX_MATCHMAKING_SESSIONS) && (m_sessions[h].localFlags & CRYSESSION_LOCAL_FLAG_USED))
3168 SSession* pSession = &m_sessions[h];
3170 if (pSession->localFlags & CRYSESSION_LOCAL_FLAG_HOST)
3172 CryMatchMakingTaskID mmTaskID;
3174 bool taskRunning = false;
3175 for (uint32 taskID = 0; taskID < MAX_MATCHMAKING_TASKS; ++taskID)
3177 STask* pTask = &m_task[taskID];
3179 if (pTask->used && pTask->running && (pTask->startedTask == eT_SessionSendHostHintExternal) && (pTask->session == h))
3181 #if NET_HOST_HINT_DEBUG
3182 NetLog("[Host Hints]: hints already in flight to PSN, will resend when done");
3183 #endif // #if NET_HOST_HINT_DEBUG
3184 pTask->numParams[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART] = eHHTB_REQUIRES_RESTART;
3185 taskRunning = true;
3186 break;
3190 if (!taskRunning)
3192 error = StartTask(eT_SessionSendHostHintExternal, false, pSession->localConnection.users[0], &mmTaskID, NULL, h, NULL, NULL);
3193 if (error == eCLE_Success)
3195 STask* pTask = &m_task[mmTaskID];
3196 pTask->numParams[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART] = eHHTB_NORMAL;
3198 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT, NULL, 1, sizeof(SHostHintParamData));
3200 if (error == eCLE_Success)
3202 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3204 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3207 else
3209 error = eCLE_InternalError;
3213 else
3215 error = eCLE_InvalidRequest;
3218 else
3220 error = eCLE_InvalidSession;
3224 NetLog("[Host Hints] Start SendHostHintExternal error %d", error);
3226 return error;
3229 void CCryPSNMatchMaking::StartSessionSendHostHintExternal(CryMatchMakingTaskID mmTaskID)
3231 STask* pTask = &m_task[mmTaskID];
3233 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT] != TMemInvalidHdl)
3235 SHostHintParamData* pHostHintParams = (SHostHintParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT]);
3236 memset(pHostHintParams, 0, sizeof(SHostHintParamData));
3237 SSession* pSession = &m_sessions[pTask->session];
3239 for (uint32 index = 0; index < pSession->newHostPriorityCount; ++index)
3241 pHostHintParams->m_memberId[index] = ((CCryPSNMatchMaking::SSession::SRConnection*)(pSession->newHostPriority[index]))->memberId;
3244 pHostHintParams->m_reqParam.roomId = pSession->m_roomId;
3245 pHostHintParams->m_reqParam.ownerPrivilegeRank = pHostHintParams->m_memberId;
3246 pHostHintParams->m_reqParam.ownerPrivilegeRankNum = pSession->newHostPriorityCount;
3248 NetLog("[Host Hints]: PSN SendHostHintExternal " PRFORMAT_SH " roomId 0x%llX Rank[0] %d RankNum %d",
3249 PRARG_SH(pTask->session), (uint64)pHostHintParams->m_reqParam.roomId, pHostHintParams->m_reqParam.ownerPrivilegeRank[0], pHostHintParams->m_reqParam.ownerPrivilegeRankNum);
3251 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3253 else
3255 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
3258 if (pTask->error != eCLE_Success)
3260 StopTaskRunning(mmTaskID);
3264 void CCryPSNMatchMaking::TickSessionSendHostHintExternal(CryMatchMakingTaskID mmTaskID)
3266 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3267 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
3269 STask* pTask = &m_task[mmTaskID];
3271 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT] != TMemInvalidHdl)
3273 SHostHintParamData* pHostHintParams = (SHostHintParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_REQUEST_SLOT]);
3275 StartSubTask(eST_WaitingForNewHostHintCallback, mmTaskID);
3277 int ret = sceNpMatching2SetRoomDataInternal(m_pPSNSupport->GetMatchmakingContextId(), &pHostHintParams->m_reqParam, NULL, &pTask->m_reqId);
3278 if (ret == PSN_OK)
3280 //-- waiting for callback
3282 else
3284 NetLog("sceNpMatching2SetRoomDataInternal : error %08X", ret);
3285 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
3286 //-- otherwise, we have to update the task error ourself.
3287 if (!m_pPSNSupport->HandlePSNError(ret))
3289 UpdateTaskError(mmTaskID, eCLE_InternalError);
3293 else
3295 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
3300 bool CCryPSNMatchMaking::EventRequestResponse_SetRoomDataInternal(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
3302 // sanity
3303 assert(pTask->subTask == eST_WaitingForNewHostHintCallback);
3304 assert(data.m_requestEvent.m_event == REQUEST_EVENT_SET_ROOM_DATA_INTERNAL);
3305 assert(data.m_requestEvent.m_dataSize == 0);
3307 if (data.m_requestEvent.m_error == 0)
3309 _this->UpdateTaskError(taskId, eCLE_Success);
3310 _this->StopTaskRunning(taskId);
3312 return true;
3314 else
3316 // return false to let the default error handler work
3317 return false;
3321 void CCryPSNMatchMaking::EndSessionSendHostHintExternal(CryMatchMakingTaskID mmTaskID)
3323 STask* pTask = &m_task[mmTaskID];
3324 if (pTask->numParams[PSN_MATCHMAKING_PSNSUPPORT_HOSTHINT_RESTART] == eHHTB_REQUIRES_RESTART)
3326 #if NET_HOST_HINT_DEBUG
3327 NetLog("[Host Hints]: hints changed whilst informing PSN, resending hints to PSN");
3328 #endif // #if NET_HOST_HINT_DEBUG
3329 SendHostHintExternal(pTask->session);
3332 #endif
3334 ECryLobbyError CCryPSNMatchMaking::SessionQuery(CrySessionHandle gh, CryLobbyTaskID* pTaskID, CryMatchmakingSessionQueryCallback pCB, void* pCBArg)
3336 ECryLobbyError error = eCLE_Success;
3338 LOBBY_AUTO_LOCK;
3340 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
3342 if ((h < MAX_MATCHMAKING_SESSIONS) && m_sessions[h].IsUsed())
3344 SSession* pSession = &m_sessions[h];
3345 CryMatchMakingTaskID mmTaskID;
3347 error = StartTask(eT_SessionQuery, false, pSession->localConnection.users[0], &mmTaskID, pTaskID, h, (void*)pCB, pCBArg);
3348 if (error == eCLE_Success)
3350 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT, NULL, 1, sizeof(SQueryParamData));
3351 if (error == eCLE_Success)
3353 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3355 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3357 else
3359 FreeTask(mmTaskID);
3363 else
3365 error = eCLE_InvalidSession;
3368 NetLog("[Lobby] Session Query Error %d", error);
3370 return error;
3373 void CCryPSNMatchMaking::TickSessionQuery(CryMatchMakingTaskID mmTaskID)
3375 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3376 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
3378 STask* pTask = &m_task[mmTaskID];
3380 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT] != TMemInvalidHdl)
3382 SQueryParamData* pQueryParams = (SQueryParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_QUERY_REQUEST_SLOT]);
3384 memset(pQueryParams, 0, sizeof(SQueryParamData));
3386 SSession* pSession = &m_sessions[pTask->session];
3388 pQueryParams->m_queryRequest.roomId = pQueryParams->m_roomIds;
3389 pQueryParams->m_queryRequest.attrId = pQueryParams->m_attrTable;
3390 pQueryParams->m_roomIds[0] = pSession->m_roomId;
3391 pQueryParams->m_queryRequest.roomIdNum = 1;
3392 pQueryParams->m_attrTable[0] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID;
3393 pQueryParams->m_attrTable[1] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_2_ID;
3394 pQueryParams->m_attrTable[2] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_3_ID;
3395 pQueryParams->m_attrTable[3] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_4_ID;
3396 pQueryParams->m_attrTable[4] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_5_ID;
3397 pQueryParams->m_attrTable[5] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_6_ID;
3398 pQueryParams->m_attrTable[6] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_7_ID;
3399 pQueryParams->m_attrTable[7] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_8_ID;
3400 pQueryParams->m_attrTable[8] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID;
3401 pQueryParams->m_attrTable[9] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID;
3402 pQueryParams->m_queryRequest.attrIdNum = 10;
3404 StartSubTask(eST_WaitingForQueryRoomRequestCallback, mmTaskID);
3406 int ret = sceNpMatching2GetRoomDataExternalList(m_pPSNSupport->GetMatchmakingContextId(), &pQueryParams->m_queryRequest, NULL, &pTask->m_reqId);
3407 if (ret == PSN_OK)
3409 //-- waiting for callback
3411 else
3413 NetLog("sceNpMatching2GetRoomDataExternalList : error %08X", ret);
3414 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
3415 //-- otherwise, we have to update the task error ourself.
3416 if (!m_pPSNSupport->HandlePSNError(ret))
3418 UpdateTaskError(mmTaskID, eCLE_InternalError);
3422 else
3424 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
3429 bool CCryPSNMatchMaking::EventRequestResponse_GetRoomDataExternalList(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
3431 // sanity
3432 assert(pTask->subTask == eST_WaitingForQueryRoomRequestCallback);
3433 assert(data.m_requestEvent.m_event == REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST);
3434 assert(data.m_requestEvent.m_dataHdl != TMemInvalidHdl);
3435 assert(data.m_requestEvent.m_dataSize == sizeof(SCryPSNSearchRoomResponse));
3437 if ((data.m_requestEvent.m_error == 0) &&
3438 (data.m_requestEvent.m_dataHdl != TMemInvalidHdl) &&
3439 (data.m_requestEvent.m_dataSize == sizeof(SCryPSNSearchRoomResponse)))
3441 // take ownership of the memory returned by the callback so it is not automatically discarded on return
3442 pTask->params[PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT] = data.m_requestEvent.m_dataHdl;
3443 data.m_requestEvent.m_dataHdl = TMemInvalidHdl;
3444 data.m_requestEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_OWNS_MEMORY;
3446 _this->UpdateTaskError(taskId, eCLE_Success);
3447 _this->StopTaskRunning(taskId);
3449 return true;
3451 else
3453 // return false to let the default error handler work
3454 return false;
3458 void CCryPSNMatchMaking::EndSessionQuery(CryMatchMakingTaskID mmTaskID)
3460 STask* pTask = &m_task[mmTaskID];
3461 SCryPSNSearchRoomResponse* pResponse = NULL;
3463 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT] != TMemInvalidHdl)
3465 pResponse = (SCryPSNSearchRoomResponse*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_QUERY_RESPONSE_SLOT]);
3468 if (pTask->error == eCLE_Success)
3470 if (pResponse)
3472 for (uint16 i = 0; i < pResponse->m_numRooms; i++)
3474 SCrySessionSearchResult result;
3475 SCrySessionUserData userData[MAX_MATCHMAKING_SESSION_USER_DATA];
3477 ProcessExternalRoomData(pResponse->m_pRooms[i], result, userData);
3479 ((CryMatchmakingSessionQueryCallback)pTask->cb)(pTask->lTaskID, eCLE_SuccessContinue, &result, pTask->cbArg);
3482 else
3484 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
3488 // free the memory allocated to the response
3489 if (pResponse)
3491 pResponse->Release(m_lobby);
3494 ((CryMatchmakingSessionQueryCallback)pTask->cb)(pTask->lTaskID, pTask->error, NULL, pTask->cbArg);
3497 ECryLobbyError CCryPSNMatchMaking::SessionGetUsers(CrySessionHandle gh, CryLobbyTaskID* pTaskID, CryMatchmakingSessionGetUsersCallback pCB, void* pCBArg)
3499 ECryLobbyError error = eCLE_Success;
3501 LOBBY_AUTO_LOCK;
3503 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
3505 if ((h < MAX_MATCHMAKING_SESSIONS) && (m_sessions[h].localFlags & CRYSESSION_LOCAL_FLAG_USED))
3507 SSession* session = &m_sessions[h];
3508 CryMatchMakingTaskID mmTaskID;
3510 error = StartTask(eT_SessionGetUsers, false, session->localConnection.users[0], &mmTaskID, pTaskID, h, (void*)pCB, pCBArg);
3512 if (error == eCLE_Success)
3514 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3517 else
3519 error = eCLE_InvalidSession;
3522 if (error != eCLE_Success)
3524 NetLog("[Lobby] Session Get Users Is Error %d", error);
3527 return error;
3530 void CCryPSNMatchMaking::GetRoomMemberData(CryLobbySessionHandle sessionHandle, SCryUserInfoResult& result, SCryMatchMakingConnectionUID& uid)
3532 SSession::SRoomMember* pRoomMember = FindRoomMemberFromRoomMemberID(sessionHandle, uid.m_uid);
3534 result.m_conID = uid;
3535 result.m_isDedicated = false; // PSN does not support dedicated servers
3537 if (pRoomMember)
3539 cry_strcpy(result.m_userName, pRoomMember->m_npId.handle.data);
3540 memcpy(result.m_userData, pRoomMember->m_userData, CRYLOBBY_USER_DATA_SIZE_IN_BYTES);
3542 ((SCryPSNUserID*)result.m_userID.get())->npId = pRoomMember->m_npId;
3544 else
3546 result.m_userName[0] = 0;
3550 void CCryPSNMatchMaking::TickSessionGetUsers(CryMatchMakingTaskID mmTaskID)
3552 STask* pTask = &m_task[mmTaskID];
3554 SCryUserInfoResult temp;
3555 temp.m_userID = new SCryPSNUserID;
3557 int a;
3559 // Glue in local user - arguably, this could all just iterate over the room members list (ho hum)
3560 GetRoomMemberData(pTask->session, temp, m_sessions[pTask->session].localConnection.uid);
3561 ((CryMatchmakingSessionGetUsersCallback)pTask->cb)(pTask->lTaskID, pTask->error, &temp, pTask->cbArg);
3563 for (a = 0; a < MAX_LOBBY_CONNECTIONS; a++)
3565 if (m_sessions[pTask->session].remoteConnection[a].used)
3567 GetRoomMemberData(pTask->session, temp, m_sessions[pTask->session].remoteConnection[a].uid);
3568 ((CryMatchmakingSessionGetUsersCallback)pTask->cb)(pTask->lTaskID, pTask->error, &temp, pTask->cbArg);
3572 StopTaskRunning(mmTaskID);
3575 ECryLobbyError CCryPSNMatchMaking::SessionStart(CrySessionHandle gh, CryLobbyTaskID* taskID, CryMatchmakingCallback cb, void* cbArg)
3577 ECryLobbyError error = eCLE_Success;
3579 LOBBY_AUTO_LOCK;
3581 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
3583 if ((h < MAX_MATCHMAKING_SESSIONS) && m_sessions[h].IsUsed())
3585 SSession* pSession = &m_sessions[h];
3586 CryMatchMakingTaskID mmTaskID;
3588 error = StartTask(eT_SessionStart, false, pSession->localConnection.users[0], &mmTaskID, taskID, h, (void*)cb, cbArg);
3590 if (error == eCLE_Success)
3592 pSession->localFlags |= CRYSESSION_LOCAL_FLAG_STARTED;
3593 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3596 else
3598 error = eCLE_InvalidSession;
3601 NetLog("[Lobby] Start SessionStart error %d", error);
3603 return error;
3606 ECryLobbyError CCryPSNMatchMaking::SessionEnd(CrySessionHandle gh, CryLobbyTaskID* taskID, CryMatchmakingCallback cb, void* cbArg)
3608 ECryLobbyError error = eCLE_Success;
3610 LOBBY_AUTO_LOCK;
3612 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
3614 if ((h < MAX_MATCHMAKING_SESSIONS) && m_sessions[h].IsUsed())
3616 SSession* pSession = &m_sessions[h];
3617 CryMatchMakingTaskID mmTaskID;
3619 error = StartTask(eT_SessionEnd, false, pSession->localConnection.users[0], &mmTaskID, taskID, h, (void*)cb, cbArg);
3621 if (error == eCLE_Success)
3623 pSession->localFlags &= ~CRYSESSION_LOCAL_FLAG_STARTED;
3624 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3627 else
3629 error = eCLE_SuccessInvalidSession;
3632 NetLog("[Lobby] Start SessionEnd error %d", error);
3634 return error;
3637 // SESSION DELETE ------------------------------------------------------------------------------------------
3639 ECryLobbyError CCryPSNMatchMaking::SessionDelete(CrySessionHandle gh, CryLobbyTaskID* taskID, CryMatchmakingCallback cb, void* cbArg)
3641 ECryLobbyError error = eCLE_Success;
3643 LOBBY_AUTO_LOCK;
3645 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
3647 if ((h < MAX_MATCHMAKING_SESSIONS) && m_sessions[h].IsUsed())
3649 SSession* pSession = &m_sessions[h];
3650 CryMatchMakingTaskID mmTaskID;
3652 // Disconnect our local connection
3653 SessionDisconnectRemoteConnectionViaNub(h, CryMatchMakingInvalidConnectionID, eDS_Local, CryMatchMakingInvalidConnectionID, eDC_UserRequested, "Session deleted");
3655 error = StartTask(eT_SessionDelete, false, pSession->localConnection.users[0], &mmTaskID, taskID, h, (void*)cb, cbArg);
3657 if (error == eCLE_Success)
3659 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT, NULL, 1, sizeof(SLeaveParamData));
3660 if (error == eCLE_Success)
3662 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT, NULL, 1, sizeof(SCryPSNOrbisWebApiLeaveSessionInput));
3663 if (error == eCLE_Success)
3665 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3667 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3669 #if NETWORK_HOST_MIGRATION
3670 // Since we're deleting this session, terminate any host migration
3671 if (pSession->hostMigrationInfo.m_state != eHMS_Idle)
3673 m_hostMigration.Terminate(&pSession->hostMigrationInfo);
3675 #endif
3676 pSession->createFlags &= ~CRYSESSION_CREATE_FLAG_MIGRATABLE;
3679 if (error != eCLE_Success)
3681 FreeTask(mmTaskID);
3685 else
3687 error = eCLE_SuccessInvalidSession;
3690 NetLog("[Lobby] Start SessionDelete error %d", error);
3692 return error;
3695 void CCryPSNMatchMaking::StartSessionDelete(CryMatchMakingTaskID mmTaskID)
3697 STask* pTask = &m_task[mmTaskID];
3698 SSession* pSession = &m_sessions[pTask->session];
3700 #if NETWORK_HOST_MIGRATION
3701 // Since we're deleting this session, terminate any host migration
3702 if (pSession->hostMigrationInfo.m_state != eHMS_Idle)
3704 m_hostMigration.Terminate(&pSession->hostMigrationInfo);
3706 #endif
3708 pSession->createFlags &= ~CRYSESSION_CREATE_FLAG_MIGRATABLE;
3709 for (uint32 i = 0; i < MAX_LOBBY_CONNECTIONS; i++)
3711 SSession::SRConnection* connection = &pSession->remoteConnection[i];
3713 if (connection->used)
3715 FreeRemoteConnection(pTask->session, i);
3719 if (pTask->error != eCLE_Success)
3721 StopTaskRunning(mmTaskID);
3725 void CCryPSNMatchMaking::TickSessionDelete(CryMatchMakingTaskID mmTaskID)
3727 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3728 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
3730 STask* pTask = &m_task[mmTaskID];
3732 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT] != TMemInvalidHdl)
3734 SLeaveParamData* pLeaveParams = (SLeaveParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT]);
3735 SSession* pSession = &m_sessions[pTask->session];
3737 memset(pLeaveParams, 0, sizeof(SLeaveParamData));
3738 pLeaveParams->m_leaveRequest.roomId = pSession->m_roomId;
3739 pLeaveParams->m_leaveRequest.optData.len = 0;
3741 StartSubTask(eST_WaitingForLeaveRoomRequestCallback, mmTaskID);
3743 int ret = sceNpMatching2LeaveRoom(m_pPSNSupport->GetMatchmakingContextId(), &pLeaveParams->m_leaveRequest, NULL, &pTask->m_reqId);
3744 if (ret == PSN_OK)
3746 //-- wait for callback
3748 else
3750 NetLog("sceNpMatching2LeaveRoom : error %08X", ret);
3752 if ((ret == SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND) || (ret == SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM) || (ret == SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM_INSTANCE))
3754 //-- To fix a bug in trying to delete a room that doesn't exist.
3755 //-- If we attempt to leave a room, and the room doesn't exist, we'll treat it the same as if we left
3756 //-- the room successfully, so call the event handler than deals with the cleanup of the room leaving.
3757 SCryPSNSupportCallbackEventData data;
3758 memset(&data, 0, sizeof(SCryPSNSupportCallbackEventData));
3759 data.m_requestEvent.m_event = REQUEST_EVENT_LEAVE_ROOM;
3760 data.m_requestEvent.m_reqId = pTask->m_reqId;
3762 EventRequestResponse_LeaveRoom(this, pTask, mmTaskID, data);
3764 else
3766 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
3767 //-- otherwise, we have to update the task error ourself.
3768 if (!m_pPSNSupport->HandlePSNError(ret))
3770 UpdateTaskError(mmTaskID, eCLE_RoomDoesNotExist);
3775 else
3777 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
3782 bool CCryPSNMatchMaking::EventRequestResponse_LeaveRoom(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
3784 // sanity
3785 assert(pTask->subTask == eST_WaitingForLeaveRoomRequestCallback);
3786 assert(data.m_requestEvent.m_event == REQUEST_EVENT_LEAVE_ROOM);
3788 if (data.m_requestEvent.m_error == 0)
3790 if (pTask->session != CryLobbyInvalidSessionHandle)
3792 SSession* pSession = &_this->m_sessions[pTask->session];
3793 if (pSession->IsUsed())
3795 if (pSession->m_sessionId.data[0] != 0)
3797 _this->StartSubTask(eST_WaitingForLeaveRoomWebApiCallback, taskId);
3799 SCryPSNOrbisWebApiLeaveSessionInput* pLeaveWebApiParams = (SCryPSNOrbisWebApiLeaveSessionInput*)_this->m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT]);
3800 if (pLeaveWebApiParams)
3802 memcpy(&pLeaveWebApiParams->sessionId, &pSession->m_sessionId, sizeof(SceNpSessionId));
3803 memcpy(&pLeaveWebApiParams->playerId, &_this->m_pPSNSupport->GetLocalNpId()->handle, sizeof(SceNpOnlineId));
3805 SLeaveParamData* pLeaveParams = (SLeaveParamData*)_this->m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_LEAVE_REQUEST_SLOT]);
3806 pLeaveParams->m_leaveJobId = _this->m_pPSNSupport->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::LeaveSession, pTask->params[PSN_MATCHMAKING_WEBAPI_LEAVE_REQUEST_SLOT]);
3808 else
3810 // failed!
3811 _this->UpdateTaskError(taskId, eCLE_OutOfMemory);
3814 else
3816 // no session advert to leave, so we're finished!
3817 _this->ClearSessionInfo(pTask->session);
3818 _this->FreeSessionHandle(pTask->session);
3820 _this->UpdateTaskError(taskId, eCLE_Success);
3821 _this->StopTaskRunning(taskId);
3824 else
3826 _this->UpdateTaskError(taskId, eCLE_InternalError);
3829 else
3831 _this->UpdateTaskError(taskId, eCLE_InternalError);
3834 return true;
3836 else
3838 return false;
3842 void CCryPSNMatchMaking::EventWebApiLeaveSession(CryMatchMakingTaskID mmTaskID, SCryPSNSupportCallbackEventData& data)
3844 STask* pTask = &m_task[mmTaskID];
3846 if (pTask->session != CryLobbyInvalidSessionHandle)
3848 SSession* pSession = &m_sessions[pTask->session];
3850 if (data.m_webApiEvent.m_error == PSN_OK)
3852 // Completed successfully
3853 // no session advert to leave, so we're finished!
3854 ClearSessionInfo(pTask->session);
3855 FreeSessionHandle(pTask->session);
3857 UpdateTaskError(mmTaskID, eCLE_Success);
3858 StopTaskRunning(mmTaskID);
3859 return;
3863 // otherwise something went wrong!
3864 ClearSessionInfo(pTask->session);
3865 FreeSessionHandle(pTask->session);
3867 UpdateTaskError(mmTaskID, eCLE_InternalError);
3868 StopTaskRunning(mmTaskID);
3871 // END SESSION DELETE -----------------------------------------------------------------------------------------------------
3873 // SESSION SEARCH ---------------------------------------------------------------------------------------------------------
3875 ECryLobbyError CCryPSNMatchMaking::SessionSearch(uint32 user, SCrySessionSearchParam* pParam, CryLobbyTaskID* pTaskID, CryMatchmakingSessionSearchCallback cb, void* cbArg)
3877 LOBBY_AUTO_LOCK;
3879 CryMatchMakingTaskID mmTaskID;
3881 ECryLobbyError error = StartTask(eT_SessionSearch, false, user, &mmTaskID, pTaskID, 0, (void*)cb, cbArg);
3882 if (error == eCLE_Success)
3884 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_SEARCH_PARAMS_SLOT, pParam, 1, sizeof(SCrySessionSearchParam));
3885 if (error == eCLE_Success)
3887 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_SEARCH_DATA_SLOT, pParam->m_data, pParam->m_numData, pParam->m_numData * sizeof(pParam->m_data[0]));
3888 if (error == eCLE_Success)
3890 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT, NULL, 1, sizeof(SSearchInfoData));
3891 if (error == eCLE_Success)
3893 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
3895 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
3900 if (error != eCLE_Success)
3902 FreeTask(mmTaskID);
3906 NetLog("[Lobby] Start SessionSearch error %d", error);
3908 return error;
3911 uint32 CCryPSNMatchMaking::BuildSearchFilterParams(SCrySessionSearchData* pData, uint32 numData,
3912 SceNpMatching2IntSearchFilter intFilterExternal[SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM])
3914 uint32 nCount = 0;
3916 if (pData)
3918 for (uint32 i = 0; (i < numData) && (nCount < SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM); i++)
3920 SCrySessionSearchData* pCurData = &pData[i];
3922 for (uint32 j = 0; (j < m_registeredUserData.num) && (nCount < SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_NUM); j++)
3924 SCrySessionUserData* pRegUserData = &m_registeredUserData.data[j];
3925 SMappingToPSNLobbyData* pRegMappingData = &m_registeredUserData.mapping[j];
3927 if (pCurData->m_data.m_id == pRegUserData->m_id)
3929 if (pCurData->m_data.m_type == pRegUserData->m_type)
3931 assert(pRegMappingData->integerField && "Can only search using integer fields on PSN!");
3933 if (pRegMappingData->integerField)
3935 intFilterExternal[nCount].attr.id = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID + pRegMappingData->fieldOffset;
3936 intFilterExternal[nCount].attr.num = pCurData->m_data.m_int32;
3938 switch (pCurData->m_operator)
3940 default:
3942 NetLog("[PSN Search] No valid Search filter operator defined: using default EQUALS");
3943 intFilterExternal[nCount].searchOperator = SCE_NP_MATCHING2_OPERATOR_EQ;
3945 break;
3946 case eCSSO_Equal:
3948 intFilterExternal[nCount].searchOperator = SCE_NP_MATCHING2_OPERATOR_EQ;
3950 break;
3951 case eCSSO_NotEqual:
3953 intFilterExternal[nCount].searchOperator = SCE_NP_MATCHING2_OPERATOR_NE;
3955 break;
3956 case eCSSO_LessThan:
3958 intFilterExternal[nCount].searchOperator = SCE_NP_MATCHING2_OPERATOR_LT;
3960 break;
3961 case eCSSO_LessThanEqual:
3963 intFilterExternal[nCount].searchOperator = SCE_NP_MATCHING2_OPERATOR_LE;
3965 break;
3966 case eCSSO_GreaterThan:
3968 intFilterExternal[nCount].searchOperator = SCE_NP_MATCHING2_OPERATOR_GT;
3970 break;
3971 case eCSSO_GreaterThanEqual:
3973 intFilterExternal[nCount].searchOperator = SCE_NP_MATCHING2_OPERATOR_GE;
3975 break;
3978 nCount++;
3980 else
3982 NetLog("[PSN Search] Can only search using integer fields on PSN!");
3990 return nCount;
3993 void CCryPSNMatchMaking::StartSessionSearch(CryMatchMakingTaskID mmTaskID)
3995 STask* pTask = &m_task[mmTaskID];
3997 if (pTask->params[PSN_MATCHMAKING_SEARCH_PARAMS_SLOT] != TMemInvalidHdl)
3999 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT] != TMemInvalidHdl)
4001 SCrySessionSearchParam* pData = (SCrySessionSearchParam*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_SEARCH_PARAMS_SLOT]);
4002 if (pTask->params[PSN_MATCHMAKING_SEARCH_DATA_SLOT] != TMemInvalidHdl)
4004 pData->m_data = (SCrySessionSearchData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_SEARCH_DATA_SLOT]);
4006 else
4008 pData->m_data = NULL;
4011 SSearchInfoData* pSearchInfo = (SSearchInfoData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
4012 memset(pSearchInfo, 0, sizeof(SSearchInfoData));
4014 uint32 nFields = BuildSearchFilterParams(pData->m_data, pData->m_numData, pSearchInfo->m_intFilterExternal);
4016 pSearchInfo->m_searchRequest.worldId = 0;
4017 pSearchInfo->m_searchRequest.lobbyId = 0;
4018 pSearchInfo->m_searchRequest.flagFilter = SCE_NP_MATCHING2_ROOM_FLAG_ATTR_CLOSED | SCE_NP_MATCHING2_ROOM_FLAG_ATTR_FULL;
4019 pSearchInfo->m_searchRequest.flagAttr = 0;
4020 pSearchInfo->m_searchRequest.intFilter = (nFields > 0) ? (pSearchInfo->m_intFilterExternal) : (NULL);
4021 pSearchInfo->m_searchRequest.intFilterNum = nFields;
4022 pSearchInfo->m_searchRequest.binFilter = NULL;
4023 pSearchInfo->m_searchRequest.binFilterNum = 0;
4024 pSearchInfo->m_searchRequest.rangeFilter.startIndex = SCE_NP_MATCHING2_RANGE_FILTER_START_INDEX_MIN;
4025 pSearchInfo->m_searchRequest.rangeFilter.max = SCE_NP_MATCHING2_RANGE_FILTER_MAX;
4026 pSearchInfo->m_searchRequest.option = SCE_NP_MATCHING2_SEARCH_ROOM_OPTION_RANDOM;
4028 pSearchInfo->m_attrId[0] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID;
4029 pSearchInfo->m_attrId[1] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_2_ID;
4030 pSearchInfo->m_attrId[2] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_3_ID;
4031 pSearchInfo->m_attrId[3] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_4_ID;
4032 pSearchInfo->m_attrId[4] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_5_ID;
4033 pSearchInfo->m_attrId[5] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_6_ID;
4034 pSearchInfo->m_attrId[6] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_7_ID;
4035 pSearchInfo->m_attrId[7] = SCE_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_8_ID;
4036 pSearchInfo->m_attrId[8] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID;
4037 pSearchInfo->m_attrId[9] = SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID;
4039 pSearchInfo->m_searchRequest.attrId = pSearchInfo->m_attrId;
4040 pSearchInfo->m_searchRequest.attrIdNum = 10;
4042 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4044 else
4046 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4047 StopTaskRunning(mmTaskID);
4050 else
4052 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4053 StopTaskRunning(mmTaskID);
4057 void CCryPSNMatchMaking::TickSessionSearch(CryMatchMakingTaskID mmTaskID)
4059 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4060 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
4062 STask* pTask = &m_task[mmTaskID];
4064 //-- get a list of worlds
4065 StartSubTask(eST_WaitingForSearchRoomWorldInfo, mmTaskID);
4067 SceNpMatching2GetWorldInfoListRequest reqParam;
4068 memset(&reqParam, 0, sizeof(reqParam));
4069 reqParam.serverId = m_pPSNSupport->GetServerInfo()->server.serverId;
4071 int ret = sceNpMatching2GetWorldInfoList(m_pPSNSupport->GetMatchmakingContextId(), &reqParam, NULL, &pTask->m_reqId);
4072 if (ret == PSN_OK)
4074 //-- Waiting for callback
4076 else
4078 NetLog("sceNpMatching2GetWorldInfoList : error %08X", ret);
4079 if (!m_pPSNSupport->HandlePSNError(ret))
4081 UpdateTaskError(mmTaskID, eCLE_WorldNotDefined);
4087 bool CCryPSNMatchMaking::EventRequestResponse_GetWorldInfoListForSearch(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
4089 assert(pTask->subTask == eST_WaitingForSearchRoomWorldInfo);
4090 assert(data.m_requestEvent.m_event == REQUEST_EVENT_GET_WORLD_INFO_LIST);
4091 assert(data.m_requestEvent.m_dataSize == sizeof(SCryPSNGetWorldInfoListResponse));
4093 if ((data.m_requestEvent.m_error == 0) &&
4094 (data.m_requestEvent.m_dataHdl != TMemInvalidHdl) &&
4095 (data.m_requestEvent.m_dataSize == sizeof(SCryPSNGetWorldInfoListResponse)))
4097 SSearchInfoData* pSearchInfo = (SSearchInfoData*)_this->m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
4098 if (pSearchInfo)
4100 const SCryPSNGetWorldInfoListResponse* pWorldList = (SCryPSNGetWorldInfoListResponse*)_this->m_lobby->MemGetPtr(data.m_requestEvent.m_dataHdl);
4102 pSearchInfo->m_numWorlds = SortWorlds(pWorldList, pSearchInfo->m_worldIds, MAX_WORLDS_TO_SEARCH, true);
4103 if (pSearchInfo->m_numWorlds > 0)
4105 pSearchInfo->m_nIndex = 0;
4106 pSearchInfo->m_searchRequest.worldId = pSearchInfo->m_worldIds[pSearchInfo->m_nIndex];
4108 _this->StartSubTask(eST_SessionSearchRequest, taskId);
4110 else
4112 _this->UpdateTaskError(taskId, eCLE_WorldNotDefined);
4115 else
4117 _this->UpdateTaskError(taskId, eCLE_OutOfMemory);
4120 return true;
4122 else
4124 return false;
4128 void CCryPSNMatchMaking::TickSessionSearchRequest(CryMatchMakingTaskID mmTaskID)
4130 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4131 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
4133 STask* pTask = &m_task[mmTaskID];
4135 SSearchInfoData* pSearchInfo = (SSearchInfoData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
4137 StartSubTask(eST_WaitingForSearchRoomRequestCallback, mmTaskID);
4139 int ret = sceNpMatching2SearchRoom(m_pPSNSupport->GetMatchmakingContextId(), &pSearchInfo->m_searchRequest, NULL, &pTask->m_reqId);
4140 if (ret == PSN_OK)
4142 //-- waiting for callback
4144 else
4146 NetLog("sceNpMatching2SearchRoom : error %08X", ret);
4147 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
4148 //-- otherwise, we have to update the task error ourself.
4149 if (!m_pPSNSupport->HandlePSNError(ret))
4151 UpdateTaskError(mmTaskID, eCLE_InternalError);
4155 else
4157 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4161 bool CCryPSNMatchMaking::EventRequestResponse_SearchRoom(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
4163 // sanity
4164 assert(pTask->subTask == eST_WaitingForSearchRoomRequestCallback);
4165 assert(data.m_requestEvent.m_event == REQUEST_EVENT_SEARCH_ROOM);
4166 assert(data.m_requestEvent.m_dataHdl != TMemInvalidHdl);
4167 assert(data.m_requestEvent.m_dataSize == sizeof(SCryPSNSearchRoomResponse));
4169 if ((data.m_requestEvent.m_error == 0) &&
4170 (data.m_requestEvent.m_dataHdl != TMemInvalidHdl) &&
4171 (data.m_requestEvent.m_dataSize == sizeof(SCryPSNSearchRoomResponse)))
4173 const SCryPSNSearchRoomResponse* const pResponse = (SCryPSNSearchRoomResponse*)_this->m_lobby->MemGetPtr(data.m_requestEvent.m_dataHdl);
4174 SSearchInfoData* pSearchInfo = (SSearchInfoData*)_this->m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
4175 SCrySessionSearchParam* pSearchParams = (SCrySessionSearchParam*)_this->m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_SEARCH_PARAMS_SLOT]);
4177 uint16 c = 0;
4178 while ((pSearchInfo->m_numResults < MAX_ROOMS_TO_STORE) && (pSearchInfo->m_numResults < pSearchParams->m_maxNumReturn) && (c < pResponse->m_numRooms))
4180 _this->ProcessExternalRoomData(pResponse->m_pRooms[c], pSearchInfo->m_results[pSearchInfo->m_numResults], pSearchInfo->m_resultUserData[pSearchInfo->m_numResults]);
4181 pSearchInfo->m_numResults++;
4182 c++;
4185 pSearchInfo->m_nIndex++;
4186 if ((pSearchInfo->m_numResults < MAX_ROOMS_TO_STORE) && (pSearchInfo->m_numResults < pSearchParams->m_maxNumReturn) && (pSearchInfo->m_nIndex < pSearchInfo->m_numWorlds))
4188 //-- Chain start a new search on the next world in the list.
4189 assert(pSearchInfo->m_worldIds[pSearchInfo->m_nIndex] != 0);
4190 pSearchInfo->m_searchRequest.worldId = pSearchInfo->m_worldIds[pSearchInfo->m_nIndex];
4191 _this->StartSubTask(eST_SessionSearchRequest, taskId);
4193 else
4195 if (pSearchInfo->m_numResults > 0)
4197 //-- We've filled the results buffer, or run out of worlds, so move onto QOS!
4198 pSearchInfo->m_nIndex = 0;
4199 _this->StartSubTask(eST_SessionSearchKickQOS, taskId);
4201 else
4203 //-- No results after searching all the worlds, so just give up on search task.
4204 _this->UpdateTaskError(taskId, eCLE_Success);
4205 _this->StopTaskRunning(taskId);
4209 return true;
4211 else
4213 // an error was returned in the response. If we return false, the default error handler will deal with it
4214 return false;
4218 void CCryPSNMatchMaking::TickSessionWaitForQOS(CryMatchMakingTaskID mmTaskID)
4220 STask* pTask = &m_task[mmTaskID];
4222 if (pTask->GetTimer() >= MAX_WAITTIME_FOR_QOS)
4224 NetLog("Timeout Getting QOS Data - Returning what we have");
4225 UpdateTaskError(mmTaskID, eCLE_Success); // Don't return timeout, that way game gets some results
4226 StopTaskRunning(mmTaskID);
4230 void CCryPSNMatchMaking::TickSessionQOSSearch(CryMatchMakingTaskID mmTaskID)
4232 int qosIndex = 0;
4234 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4235 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
4237 STask* pTask = &m_task[mmTaskID];
4239 SSearchInfoData* pSearchInfo = (SSearchInfoData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
4240 pSearchInfo->m_nIndex = 0;
4241 while (qosIndex < pSearchInfo->m_numResults)
4243 SCryPSNSessionID* pId = (SCryPSNSessionID*)pSearchInfo->m_results[qosIndex].m_id.get();
4244 if (pId)
4246 memset(&pSearchInfo->m_QOSRequest[qosIndex], 0, sizeof(SceNpMatching2SignalingGetPingInfoRequest));
4247 pSearchInfo->m_QOSRequest[qosIndex].roomId = pId->m_sessionInfo.m_roomId;
4248 pSearchInfo->m_results[qosIndex].m_ping = PSN_MATCHMAKING_DEFAULT_UNKNOWN_PING;
4250 pTask->m_reqId = INVALID_PSN_REQUEST_ID; // We cant use the global task id, because we have many qos subtasks potentially on one task
4252 StartSubTask(eST_WaitingForSearchQOSRequestCallback, mmTaskID);
4254 int ret = sceNpMatching2SignalingGetPingInfo(m_pPSNSupport->GetMatchmakingContextId(), &pSearchInfo->m_QOSRequest[qosIndex], NULL, &pSearchInfo->m_reqId[qosIndex]);
4256 NetLog("Task ID : %d Idx : %d Request id : %d Room Id : %d", mmTaskID, qosIndex, (int32)pSearchInfo->m_reqId[qosIndex], (int32)pId->m_sessionInfo.m_roomId);
4257 qosIndex++;
4259 if (ret == PSN_OK)
4261 //-- waiting for callback
4263 else
4265 NetLog("sceNpMatching2SignalingGetPingInfo : error %08X", ret);
4266 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
4267 //-- otherwise, we have to update the task error ourself.
4268 if (!m_pPSNSupport->HandlePSNError(ret))
4270 UpdateTaskError(mmTaskID, eCLE_InternalError);
4274 else
4276 UpdateTaskError(mmTaskID, eCLE_InternalError);
4279 pSearchInfo->m_nIndex = qosIndex;
4282 if (pSearchInfo->m_nIndex == 0)
4284 //-- SUCCESS End of search results, we can end the task now.
4285 UpdateTaskError(mmTaskID, eCLE_Success);
4286 StopTaskRunning(mmTaskID);
4288 else
4290 pTask->StartTimer();
4295 bool CCryPSNMatchMaking::EventRequestResponse_SearchQOS(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
4297 assert(pTask->subTask == eST_WaitingForSearchQOSRequestCallback);
4298 assert(data.m_requestEvent.m_event == REQUEST_EVENT_SIGNALING_GET_PING_INFO);
4299 assert(data.m_requestEvent.m_dataHdl != TMemInvalidHdl);
4300 assert(data.m_requestEvent.m_dataSize == sizeof(SCryPSNSignalingGetPingInfoResponse));
4302 SSearchInfoData* pSearchInfo = (SSearchInfoData*)_this->m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
4303 SCrySessionSearchResult* pSearchResult = NULL;
4305 for (int a = 0; a < pSearchInfo->m_numResults; a++)
4307 if (data.m_requestEvent.m_reqId == pSearchInfo->m_reqId[a])
4309 pSearchResult = &pSearchInfo->m_results[a];
4310 pSearchInfo->m_nIndex--;
4311 break;
4315 if ((data.m_requestEvent.m_error == 0) &&
4316 (data.m_requestEvent.m_dataHdl != TMemInvalidHdl) &&
4317 (data.m_requestEvent.m_dataSize == sizeof(SCryPSNSignalingGetPingInfoResponse)) &&
4318 pSearchResult)
4320 const SCryPSNSignalingGetPingInfoResponse* const pQOSResponse = (SCryPSNSignalingGetPingInfoResponse*)_this->m_lobby->MemGetPtr(data.m_requestEvent.m_dataHdl);
4321 pSearchResult->m_ping = pQOSResponse->m_rtt / 1000;
4322 NetLog("Request Id: %d QoS Done: ping %d roomId %d", data.m_requestEvent.m_reqId, (int32)pSearchResult->m_ping, (int32)pQOSResponse->m_roomId);
4324 else
4326 // QoS can return socket errors, or a timeout as an error. In this rare case, we'll have to assume the error is not fatal and trap it
4327 // by marking it as handled with no ping value.
4328 NetLog("Request Id: %d QoS Done ERROR: ping %d, error %08X", data.m_requestEvent.m_reqId, (int32)pSearchResult->m_ping, data.m_requestEvent.m_error);
4331 if (pSearchInfo->m_nIndex == 0)
4333 //-- SUCCESS End of search results, we can end the task now.
4334 _this->UpdateTaskError(taskId, eCLE_Success);
4335 _this->StopTaskRunning(taskId);
4338 return true;
4341 void CCryPSNMatchMaking::EndSessionSearch(CryMatchMakingTaskID mmTaskID)
4343 STask* pTask = &m_task[mmTaskID];
4345 if (pTask->error == eCLE_Success)
4347 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT] != TMemInvalidHdl)
4349 SSearchInfoData* pSearchInfo = (SSearchInfoData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_SEARCH_INFO_SLOT]);
4351 NetLog("[Lobby] Found %d sessions in %d worlds.", pSearchInfo->m_numResults, pSearchInfo->m_numWorlds);
4353 for (uint32 i = 0; i < pSearchInfo->m_numResults; i++)
4355 SCrySessionSearchResult* pResult = &pSearchInfo->m_results[i];
4356 ((CryMatchmakingSessionSearchCallback)pTask->cb)(pTask->lTaskID, eCLE_SuccessContinue, pResult, pTask->cbArg);
4358 //-- remove reference to CrySessionID, since it's a smart pointer inside a larger alloc that wouldn't be cleaned up otherwise.
4359 pResult->m_id = NULL;
4362 else
4364 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4368 ((CryMatchmakingSessionSearchCallback)pTask->cb)(pTask->lTaskID, pTask->error, NULL, pTask->cbArg);
4371 // END OF SEARCH -------------------------------------------------------------------------
4373 // SESSION JOIN --------------------------------------------------------------------------
4375 ECryLobbyError CCryPSNMatchMaking::SessionJoin(uint32* users, int numUsers, uint32 flags, CrySessionID id, CryLobbyTaskID* taskID, CryMatchmakingSessionJoinCallback cb, void* cbArg)
4377 LOBBY_AUTO_LOCK;
4379 CryLobbySessionHandle h;
4380 ECryLobbyError error = CreateSessionHandle(&h, false, users, numUsers, flags);
4381 if (error == eCLE_Success)
4383 CryMatchMakingTaskID mmTaskID;
4385 error = StartTask(eT_SessionJoin, false, users[0], &mmTaskID, taskID, h, (void*)cb, cbArg);
4386 if (error == eCLE_Success)
4388 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT, NULL, 1, sizeof(SJoinParamData));
4389 if (error == eCLE_Success)
4391 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_WEBAPI_JOIN_SLOT, NULL, 1, sizeof(SCryPSNOrbisWebApiJoinSessionInput));
4392 if (error == eCLE_Success)
4394 SCryPSNSessionID* psnID = (SCryPSNSessionID*)id.get();
4395 SSession* pSession = &m_sessions[h];
4397 pSession->m_roomId = psnID->m_sessionInfo.m_roomId;
4398 pSession->m_worldId = psnID->m_sessionInfo.m_worldId;
4399 pSession->m_serverId = psnID->m_sessionInfo.m_serverId;
4400 pSession->m_gameType = psnID->m_sessionInfo.m_gameType;
4401 pSession->m_flags = 0;
4403 for (uint32 i = 0; i < numUsers; i++)
4405 pSession->localConnection.privateSlot[i] = psnID->m_fromInvite;
4408 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4410 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
4414 if (error != eCLE_Success)
4416 FreeTask(mmTaskID);
4417 FreeSessionHandle(h);
4420 else
4422 FreeSessionHandle(h);
4426 NetLog("[Lobby] Start SessionJoin error %d", error);
4428 return error;
4431 void CCryPSNMatchMaking::TickSessionJoin(CryMatchMakingTaskID mmTaskID)
4433 STask* pTask = &m_task[mmTaskID];
4435 if (pTask->error == eCLE_Success)
4437 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4438 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
4440 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT] != TMemInvalidHdl)
4442 SJoinParamData* pJoinParams = (SJoinParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT]);
4443 SSession* pSession = &m_sessions[pTask->session];
4445 memset(pJoinParams, 0, sizeof(SJoinParamData));
4447 pJoinParams->m_joinRequest.roomId = pSession->m_roomId;
4448 pJoinParams->m_joinRequest.roomPassword = NULL;
4449 pJoinParams->m_joinRequest.joinRoomGroupLabel = NULL;
4450 pJoinParams->m_joinRequest.roomMemberBinAttrInternal = NULL;
4451 pJoinParams->m_joinRequest.roomMemberBinAttrInternalNum = 0;
4452 pJoinParams->m_joinRequest.optData.len = 0;
4454 StartSubTask(eST_WaitingForJoinRoomRequestCallback, mmTaskID);
4456 int ret = sceNpMatching2JoinRoom(m_pPSNSupport->GetMatchmakingContextId(), &pJoinParams->m_joinRequest, NULL, &pTask->m_reqId);
4457 if (ret == PSN_OK)
4459 //-- waiting for callback
4461 else
4463 NetLog("sceNpMatching2JoinRoom : error %08X", ret);
4464 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
4465 //-- otherwise, we have to update the task error ourself.
4466 if (!m_pPSNSupport->HandlePSNError(ret))
4468 UpdateTaskError(mmTaskID, eCLE_InternalError);
4472 else
4474 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4480 bool CCryPSNMatchMaking::EventRequestResponse_JoinRoom(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
4482 // sanity
4483 assert(pTask->subTask == eST_WaitingForJoinRoomRequestCallback);
4484 assert(data.m_requestEvent.m_event == REQUEST_EVENT_JOIN_ROOM);
4485 assert(data.m_requestEvent.m_dataHdl != TMemInvalidHdl);
4486 assert(data.m_requestEvent.m_dataSize == sizeof(SCryPSNJoinRoomResponse));
4488 if ((data.m_requestEvent.m_error == 0) &&
4489 (data.m_requestEvent.m_dataHdl != TMemInvalidHdl) &&
4490 (data.m_requestEvent.m_dataSize == sizeof(SCryPSNJoinRoomResponse)))
4492 if (pTask->session != CryLobbyInvalidSessionHandle)
4494 SSession* pSession = &_this->m_sessions[pTask->session];
4495 if (pSession->IsUsed())
4497 const SCryPSNJoinRoomResponse* const pJoinResponse = (SCryPSNJoinRoomResponse*)_this->m_lobby->MemGetPtr(data.m_requestEvent.m_dataHdl);
4498 pSession->m_roomId = pJoinResponse->m_roomInfo.m_roomId;
4500 if (!pTask->canceled)
4502 _this->AddInitialRoomMembers(pTask->session, pJoinResponse->m_roomMembers);
4504 // take ownership of the memory returned by the callback so it is not automatically discarded on return
4505 pTask->params[PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT] = data.m_requestEvent.m_dataHdl;
4506 data.m_requestEvent.m_dataHdl = TMemInvalidHdl;
4507 data.m_requestEvent.m_returnFlags |= SCryPSNSupportCallbackEventData::SRequestEvent::REQUEST_EVENT_OWNS_MEMORY;
4509 _this->StartSubTask(eST_WaitingForJoinRoomSignalingCallback, taskId);
4511 else
4513 _this->UpdateTaskError(taskId, eCLE_IllegalSessionJoin);
4516 else
4518 _this->UpdateTaskError(taskId, eCLE_InternalError);
4521 else
4523 _this->UpdateTaskError(taskId, eCLE_InternalError);
4526 return true;
4528 else
4530 return false;
4534 void CCryPSNMatchMaking::ProcessSessionJoinHostAck(const TNetAddress& addr, CCrySharedLobbyPacket* pPacket)
4536 CryLobbySessionHandle h = CryLobbyInvalidSessionHandle;
4537 SCryMatchMakingConnectionUID hostUID = pPacket->GetFromConnectionUID();
4538 CryMatchMakingConnectionID mmCxID = CryMatchMakingInvalidConnectionID;
4540 if (FindConnectionFromUID(hostUID, &h, &mmCxID))
4542 SSession* pSession = &m_sessions[h];
4544 NetLog("[join session]: received join session server acknowledgment " PRFORMAT_SHMMCINFO, PRARG_SHMMCINFO(h, mmCxID, pSession->remoteConnection[mmCxID].connectionID, hostUID));
4546 // part of the join session ack packet is the host's session id, which we want to copy.
4547 pPacket->ReadString((char*)&pSession->m_sessionId, sizeof(SceNpSessionId));
4549 for (uint32 a = 0; a < MAX_PSN_ROOM_MEMBERS; a++)
4551 SSession::SRoomMember* pMember = &pSession->m_members[a];
4552 if (pMember->IsValid(ePSNMI_Owner))
4554 if ((pMember->m_signalingState == ePSNCS_Active) || (pMember->m_signalingState == ePSNCS_Pending))
4556 pMember->m_bHostJoinAck = true;
4558 for (uint32 i = 0; i < MAX_MATCHMAKING_TASKS; i++)
4560 STask* pTask = &m_task[i];
4562 if (pTask->used && pTask->running && (pTask->subTask == eST_WaitingForJoinRoomSignalingCallback))
4564 TickSessionJoinSignaling(i);
4568 break;
4572 else
4574 NetLog("[join session]: received join session server acknowledgement from unknown host " PRFORMAT_UID, PRARG_UID(hostUID));
4578 void CCryPSNMatchMaking::TickSessionJoinSignaling(CryMatchMakingTaskID mmTaskID)
4580 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4581 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
4583 STask* pTask = &m_task[mmTaskID];
4585 UpdateSignaling(mmTaskID);
4587 switch (CheckSignaling(mmTaskID))
4589 case ePSNCS_None:
4591 //-- This is bad, means there is no room owner!
4592 UpdateTaskError(mmTaskID, eCLE_InvalidParam);
4594 break;
4595 case ePSNCS_Active:
4597 assert(pTask->subTask == eST_WaitingForJoinRoomSignalingCallback);
4599 //-- Success! We can talk to the server p2p, and we also have the hosts session Id
4600 // Next step is to join the same session via webapi.
4601 if (!pTask->canceled)
4603 if (pTask->session != CryLobbyInvalidSessionHandle)
4605 SSession* pSession = &m_sessions[pTask->session];
4606 if (pSession->IsUsed())
4608 if (pSession->createFlags & CRYSESSION_CREATE_FLAG_INVITABLE)
4610 if (pSession->m_sessionId.data[0] != 0)
4612 SJoinParamData* pJoinParams = (SJoinParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_JOIN_REQUEST_SLOT]);
4613 SCryPSNOrbisWebApiJoinSessionInput* pWebApiJoinParams = (SCryPSNOrbisWebApiJoinSessionInput*)m_pPSNSupport->GetLobby()->MemGetPtr(pTask->params[PSN_MATCHMAKING_WEBAPI_JOIN_SLOT]);
4614 if (pJoinParams && pWebApiJoinParams)
4616 StartSubTask(eST_WaitingForJoinRoomWebApiCallback, mmTaskID);
4618 memcpy(&pWebApiJoinParams->sessionId, &pSession->m_sessionId, sizeof(SceNpSessionId));
4620 pJoinParams->m_joinJobId = m_pPSNSupport->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::JoinSession, pTask->params[PSN_MATCHMAKING_WEBAPI_JOIN_SLOT]);
4621 if (pJoinParams->m_joinJobId == INVALID_WEBAPI_JOB_ID)
4623 // failed
4624 UpdateTaskError(mmTaskID, eCLE_InternalError);
4627 else
4629 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4632 else
4634 // missing session Id
4635 UpdateTaskError(mmTaskID, eCLE_InvalidParam);
4638 else
4640 // Session is not invitable, so we don't need to join a webapi session
4641 // This is the end of Join! Success!
4642 UpdateTaskError(mmTaskID, eCLE_Success);
4643 StopTaskRunning(mmTaskID);
4646 else
4648 // session not in use
4649 UpdateTaskError(mmTaskID, eCLE_InternalError);
4652 else
4654 // invalid session handle
4655 UpdateTaskError(mmTaskID, eCLE_InternalError);
4658 else
4660 // cancelled
4661 UpdateTaskError(mmTaskID, eCLE_IllegalSessionJoin);
4664 break;
4665 case ePSNCS_Dead:
4667 assert(pTask->subTask == eST_WaitingForJoinRoomSignalingCallback);
4669 //-- Failed! We cannot talk to the server via p2p, so we've failed at the last hurdle! Join task completed(failed)
4670 UpdateTaskError(mmTaskID, eCLE_ConnectionFailed);
4672 break;
4677 void CCryPSNMatchMaking::EventWebApiJoinSession(CryMatchMakingTaskID mmTaskID, SCryPSNSupportCallbackEventData& data)
4679 STask* pTask = &m_task[mmTaskID];
4681 if (pTask->session != CryLobbyInvalidSessionHandle)
4683 SSession* pSession = &m_sessions[pTask->session];
4685 if (data.m_webApiEvent.m_error == PSN_OK)
4687 // Completed successfully
4688 UpdateTaskError(mmTaskID, eCLE_Success);
4689 StopTaskRunning(mmTaskID);
4690 return;
4694 // otherwise something went wrong!
4695 UpdateTaskError(mmTaskID, eCLE_InternalError);
4696 StopTaskRunning(mmTaskID);
4699 void CCryPSNMatchMaking::EndSessionJoin(CryMatchMakingTaskID mmTaskID)
4701 uint32 myIP = 0, myPort = 0;
4702 STask* pTask = &m_task[mmTaskID];
4703 SSession* pSession = &m_sessions[pTask->session];
4705 SCryPSNJoinRoomResponse* pResponse = NULL;
4707 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT] != TMemInvalidHdl)
4709 pResponse = (SCryPSNJoinRoomResponse*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_JOIN_RESPONSE_SLOT]);
4712 if (pTask->error == eCLE_Success)
4714 if (pResponse)
4716 SSession::SRoomMember* pMember = FindRoomMemberFromRoomMemberID(pTask->session, pSession->m_ownerMemberId);
4718 if (pSession->m_ownerMemberId != pSession->m_myMemberId)
4720 if (pMember && (pMember->m_signalingState == ePSNCS_Active))
4722 SCryMatchMakingConnectionUID matchingUID;
4723 myIP = pMember->m_peerAddr.s_addr;
4724 myPort = pMember->m_peerPort;
4726 matchingUID.m_uid = pSession->m_myMemberId;
4727 matchingUID.m_sid = pSession->m_roomId;
4729 pSession->localConnection.uid = matchingUID;
4730 pSession->localConnection.pingToServer = CRYLOBBY_INVALID_PING;
4731 pSession->localConnection.used = true;
4733 uint16 sessionCreateGameFlags = 0;
4734 memcpy(&sessionCreateGameFlags, pResponse->m_roomInfo.m_binAttributes[0].m_data, sizeof(sessionCreateGameFlags));
4735 pSession->createFlags = (pSession->createFlags & CRYSESSION_CREATE_FLAG_SYSTEM_MASK) | (sessionCreateGameFlags << CRYSESSION_CREATE_FLAG_GAME_FLAGS_SHIFT);
4737 bool hostMigrationSupported = m_lobby->GetLobbyServiceFlag(m_serviceType, eCLSF_SupportHostMigration);
4738 if ((pSession->createFlags & CRYSESSION_CREATE_FLAG_MIGRATABLE) && hostMigrationSupported)
4740 pSession->localFlags |= CRYSESSION_LOCAL_FLAG_CAN_SEND_HOST_HINTS;
4743 matchingUID.m_uid = pSession->m_ownerMemberId;
4744 CryLobbySessionHandle h;
4745 FindConnectionFromUID(matchingUID, &h, &pSession->hostConnectionID);
4746 assert(h == pTask->session);
4748 // if (pSession->createFlags & CRYSESSION_CREATE_FLAG_INVITABLE)
4749 // {
4750 // if (m_pService->GetLobbyUI())
4751 // {
4752 // ((CCryPSNLobbyUI*)m_pService->GetLobbyUI())->SetStoredInviteSessionHandle(CreateGameSessionHandle(pTask->session, CryMatchMakingInvalidConnectionUID));
4753 // }
4754 // }
4756 else
4758 UpdateTaskError(mmTaskID, eCLE_InternalError);
4761 else
4763 // we've become the owner in the middle of joining, that won't end well,
4764 // so terminate here
4765 UpdateTaskError(mmTaskID, eCLE_ConnectionFailed);
4768 else
4770 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4774 // free the memory allocated to the response
4775 if (pResponse)
4777 pResponse->Release(m_lobby);
4780 ((CryMatchmakingSessionJoinCallback)pTask->cb)(pTask->lTaskID, pTask->error, CreateGameSessionHandle(pTask->session, pSession->localConnection.uid), myIP, myPort, pTask->cbArg);
4782 if (pTask->error == eCLE_Success)
4784 InitialUserDataEvent(pTask->session);
4788 // END SESSION JOIN -------------------------------------------------------------
4790 // SESSION UPDATE USER ---------------------------------------------------------------
4792 ECryLobbyError CCryPSNMatchMaking::SessionSetLocalUserData(CrySessionHandle gh, CryLobbyTaskID* pTaskID, uint32 user, uint8* pData, uint32 dataSize, CryMatchmakingCallback pCB, void* pCBArg)
4794 ECryLobbyError error = eCLE_Success;
4796 LOBBY_AUTO_LOCK;
4798 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
4800 if ((h < MAX_MATCHMAKING_SESSIONS) && m_sessions[h].IsUsed())
4802 SSession* session = &m_sessions[h];
4804 if (dataSize <= CRYLOBBY_USER_DATA_SIZE_IN_BYTES)
4806 CryMatchMakingTaskID mmTaskID;
4808 error = StartTask(eT_SessionUserData, false, session->localConnection.users[0], &mmTaskID, pTaskID, h, (void*)pCB, pCBArg);
4809 if (error == eCLE_Success)
4811 STask* task = &m_task[mmTaskID];
4813 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_USERDATA_DATA_SLOT, pData, dataSize, dataSize);
4814 if (error == eCLE_Success)
4816 error = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT, NULL, 1, sizeof(SUserDataParamData));
4817 if (error == eCLE_Success)
4819 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4821 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
4823 else
4825 FreeTask(mmTaskID);
4828 else
4830 FreeTask(mmTaskID);
4834 else
4836 error = eCLE_OutOfUserData;
4839 else
4841 error = eCLE_InvalidSession;
4844 NetLog("[Lobby] Start SessionUpdate error %d", error);
4846 return error;
4849 void CCryPSNMatchMaking::TickSessionUserData(CryMatchMakingTaskID mmTaskID)
4851 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
4852 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
4854 STask* pTask = &m_task[mmTaskID];
4856 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT] != TMemInvalidHdl)
4858 SUserDataParamData* pUserDataParams = (SUserDataParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_USERDATA_REQUEST_SLOT]);
4860 if (pTask->params[PSN_MATCHMAKING_USERDATA_DATA_SLOT] != TMemInvalidHdl)
4862 uint8* pData = (uint8*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_USERDATA_DATA_SLOT]);
4863 SSession* pSession = &m_sessions[pTask->session];
4865 memset((void*)pUserDataParams, 0, sizeof(SUserDataParamData));
4867 memcpy(pUserDataParams->m_binAttrInternalData, pData, pTask->numParams[PSN_MATCHMAKING_USERDATA_DATA_SLOT]);
4868 pUserDataParams->m_userDataRequest.roomMemberBinAttrInternal = pUserDataParams->m_binAttrInternal;
4870 pUserDataParams->m_userDataRequest.roomId = pSession->m_roomId;
4871 pUserDataParams->m_userDataRequest.memberId = 0; // This is allowed, and means update my own data
4872 pUserDataParams->m_userDataRequest.teamId = 0;
4874 for (int a = 0; a < SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_NUM; a++)
4876 pUserDataParams->m_binAttrInternal[a].id = SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_1_ID + a;
4877 pUserDataParams->m_binAttrInternal[a].ptr = &pUserDataParams->m_binAttrInternalData[a * SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_MAX_SIZE];
4878 pUserDataParams->m_binAttrInternal[a].size = SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_MAX_SIZE;
4880 pUserDataParams->m_userDataRequest.roomMemberBinAttrInternalNum = SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_NUM;
4882 StartSubTask(eST_WaitingForUserDataRequestCallback, mmTaskID);
4884 int ret = sceNpMatching2SetRoomMemberDataInternal(m_pPSNSupport->GetMatchmakingContextId(), &pUserDataParams->m_userDataRequest, NULL, &pTask->m_reqId);
4885 if (ret == PSN_OK)
4887 //-- Waiting for callback
4889 else
4891 NetLog("sceNpMatching2SetRoomMemberDataInternal : error %08X", ret);
4892 if (!m_pPSNSupport->HandlePSNError(ret))
4894 UpdateTaskError(mmTaskID, eCLE_InternalError);
4898 else
4900 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4903 else
4905 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
4910 bool CCryPSNMatchMaking::EventRequestResponse_SetRoomMemberDataInternal(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
4912 // sanity tests
4913 assert(pTask->subTask == eST_WaitingForUserDataRequestCallback);
4914 assert(data.m_requestEvent.m_event == REQUEST_EVENT_SET_ROOM_MEMBER_DATA_INTERNAL);
4915 assert(data.m_requestEvent.m_dataSize == 0);
4917 if (data.m_requestEvent.m_error == 0)
4919 // We don't really care if this SetRoomMemberDataInternal succeeds for fails, so we'll just mark the task as complete
4920 _this->UpdateTaskError(taskId, eCLE_Success);
4921 _this->StopTaskRunning(taskId);
4923 // this event is handled
4924 return true;
4926 else
4928 // return false to let the default error handler work
4929 return false;
4933 // END SESSION UPDATE USER ------------------------------------------------------------------------
4935 void CCryPSNMatchMaking::OnPacket(const TNetAddress& addr, CCryLobbyPacket* pPacket)
4937 CCrySharedLobbyPacket* pSPacket = (CCrySharedLobbyPacket*)pPacket;
4939 switch (pSPacket->StartRead())
4941 #if NETWORK_HOST_MIGRATION
4942 case ePSNPT_HostMigrationStart:
4943 ProcessHostMigrationStart(addr, pSPacket);
4944 break;
4946 case ePSNPT_HostMigrationServer:
4947 ProcessHostMigrationFromServer(addr, pSPacket);
4948 break;
4949 #endif
4951 case ePSNPT_JoinSessionAck:
4952 ProcessSessionJoinHostAck(addr, pSPacket);
4953 break;
4955 default:
4956 CCryMatchMaking::OnPacket(addr, pSPacket);
4957 break;
4961 void CCryPSNMatchMaking::SessionUserDataEvent(ECryLobbySystemEvent event, CryLobbySessionHandle h, CryMatchMakingConnectionID id)
4963 SSession* pSession = &m_sessions[h];
4965 if (pSession->localFlags & CRYSESSION_LOCAL_FLAG_USER_DATA_EVENTS_STARTED)
4967 SCryUserInfoResult userInfo;
4968 userInfo.m_userID = new SCryPSNUserID;
4970 if (id == CryMatchMakingInvalidConnectionID)
4972 SSession::SLConnection* pConnection = &pSession->localConnection;
4973 GetRoomMemberData(h, userInfo, pConnection->uid);
4975 else
4977 SSession::SRConnection* pConnection = &pSession->remoteConnection[id];
4978 GetRoomMemberData(h, userInfo, pConnection->uid);
4981 CCryMatchMaking::SessionUserDataEvent(event, h, &userInfo);
4985 void CCryPSNMatchMaking::InitialUserDataEvent(CryLobbySessionHandle h)
4987 SSession* pSession = &m_sessions[h];
4989 pSession->localFlags |= CRYSESSION_LOCAL_FLAG_USER_DATA_EVENTS_STARTED;
4991 SessionUserDataEvent(eCLSE_SessionUserJoin, h, CryMatchMakingInvalidConnectionID);
4993 for (uint32 i = 0; i < MAX_LOBBY_CONNECTIONS; i++)
4995 SSession::SRConnection* pConnection = &pSession->remoteConnection[i];
4997 if (pConnection->used)
4999 SessionUserDataEvent(eCLSE_SessionUserJoin, h, i);
5004 #if NETWORK_HOST_MIGRATION
5005 void CCryPSNMatchMaking::HostMigrationInitialise(CryLobbySessionHandle h, EDisconnectionCause cause)
5007 SSession* pSession = &m_sessions[h];
5009 pSession->hostMigrationInfo.Reset();
5012 ECryLobbyError CCryPSNMatchMaking::HostMigrationServer(SHostMigrationInfo* pInfo)
5014 ECryLobbyError error = eCLE_Success;
5016 LOBBY_AUTO_LOCK;
5018 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(pInfo->m_session);
5019 if (h != CryLobbyInvalidSessionHandle)
5021 SSession* pSession = &m_sessions[h];
5022 CryMatchMakingTaskID mmTaskID;
5024 pSession->localFlags |= CRYSESSION_LOCAL_FLAG_HOST;
5025 pSession->hostConnectionID = CryMatchMakingInvalidConnectionID;
5026 error = StartTask(eT_SessionMigrateHostServer, false, pSession->localConnection.users[0], &mmTaskID, NULL, h, NULL, NULL);
5028 if (error == eCLE_Success)
5030 STask* pTask = &m_task[mmTaskID];
5031 #if HOST_MIGRATION_SOAK_TEST_BREAK_DETECTION
5032 DetectHostMigrationTaskBreak(h, "HostMigrationServer()");
5033 #endif
5034 pSession->hostMigrationInfo.m_taskID = pTask->lTaskID;
5036 NetLog("[Host Migration]: matchmaking migrating " PRFORMAT_SH " on the SERVER", PRARG_SH(h));
5037 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
5040 else
5042 error = eCLE_InvalidSession;
5045 if (error != eCLE_Success)
5047 NetLog("[Host Migration]: CCryPSNMatchMaking::HostMigrationServer(): " PRFORMAT_SH ", error %d", PRARG_SH(h), error);
5050 return error;
5053 void CCryPSNMatchMaking::HostMigrationServerNT(CryMatchMakingTaskID mmTaskID)
5055 STask* task = &m_task[mmTaskID];
5056 task->StartTimer();
5059 void CCryPSNMatchMaking::TickHostMigrationServerNT(CryMatchMakingTaskID mmTaskID)
5061 STask* pTask = &m_task[mmTaskID];
5062 SSession* pSession = &m_sessions[pTask->session];
5064 if (pTask->canceled)
5066 NetLog("[Host Migration]: TickHostMigrationServerNT() cancelled for " PRFORMAT_SH " - bailing", PRARG_SH(pTask->session));
5067 StopTaskRunning(mmTaskID);
5068 return;
5071 float timeout = CLobbyCVars::Get().hostMigrationTimeout * 1000.0f;
5072 if (pTask->GetTimer() > timeout)
5074 StopTaskRunning(mmTaskID);
5075 return;
5078 NetLog("[Host Migration]: matchmaking SERVER migrated " PRFORMAT_SH " successfully - informing CLIENTS", PRARG_SH(pTask->session));
5080 const uint32 MaxBufferSize = CryLobbyPacketHeaderSize;
5081 uint8 buffer[MaxBufferSize];
5082 CCrySharedLobbyPacket packet;
5084 packet.SetWriteBuffer(buffer, MaxBufferSize);
5085 packet.StartWrite(ePSNPT_HostMigrationServer, true);
5087 #if !defined(CRYNETWORK_RELEASEBUILD)
5088 int count = 0;
5089 CCryMatchMaking::SSession* pSession = CCryMatchMaking::m_sessions[pTask->session];
5090 for (uint32 i = 0; i < MAX_LOBBY_CONNECTIONS; i++)
5092 CCryMatchMaking::SSession::SRConnection* pConnection = pSession->remoteConnection[i];
5094 if (pConnection->used)
5096 TNetAddress ip;
5097 if (m_lobby->AddressFromConnection(ip, pConnection->connectionID))
5099 NetLog(" sending to " PRFORMAT_ADDR " client, " PRFORMAT_MMCINFO, PRARG_ADDR(ip), PRARG_MMCINFO(CryMatchMakingConnectionID(i), pConnection->connectionID, pConnection->uid));
5102 ++count;
5105 NetLog(" sending to %i clients", count);
5106 #endif
5108 SendToAll(mmTaskID, &packet, pTask->session, CryMatchMakingInvalidConnectionID);
5109 m_lobby->FlushMessageQueue();
5111 pSession->hostMigrationInfo.m_sessionMigrated = true;
5112 pSession->hostMigrationInfo.m_matchMakingFinished = true;
5113 StopTaskRunning(mmTaskID);
5116 void CCryPSNMatchMaking::ProcessHostMigrationFromServer(const TNetAddress& addr, CCrySharedLobbyPacket* pPacket)
5118 CryLobbySessionHandle h = CryLobbyInvalidSessionHandle;
5119 SCryMatchMakingConnectionUID hostUID = pPacket->GetFromConnectionUID();
5120 CryMatchMakingConnectionID mmCxID = CryMatchMakingInvalidConnectionID;
5122 if (FindConnectionFromUID(hostUID, &h, &mmCxID))
5124 SSession* pSession = &m_sessions[h];
5125 if (pSession->localFlags & CRYSESSION_LOCAL_FLAG_HOST)
5127 NetLog("[Host Migration]: ignoring session details from " PRFORMAT_SHMMCINFO " as I am already the server " PRFORMAT_UID,
5128 PRARG_SHMMCINFO(h, mmCxID, pSession->remoteConnection[mmCxID].connectionID, hostUID), PRARG_UID(pSession->localConnection.uid));
5130 else
5132 NetLog("[Host Migration]: matchmaking CLIENT received session details from " PRFORMAT_SHMMCINFO " - migrating to new PSN session",
5133 PRARG_SHMMCINFO(h, mmCxID, pSession->remoteConnection[mmCxID].connectionID, hostUID));
5134 NetLog("[Host Migration]: matchmaking CLIENT received server confirmation for " PRFORMAT_SH " - migrating to new session", PRARG_SH(h));
5136 SSession* pSession = &m_sessions[h];
5137 if (pSession->hostMigrationInfo.m_state == eHMS_Idle)
5139 NetLog("[Host Migration]: received server confirmation before host migration initiated - initiating now");
5140 HostMigrationInitiate(h, eDC_Unknown);
5143 pSession->localFlags &= ~CRYSESSION_LOCAL_FLAG_HOST;
5144 pSession->hostMigrationInfo.m_sessionMigrated = true;
5145 pSession->hostMigrationInfo.m_matchMakingFinished = true;
5147 if (pSession->m_ownerMemberId == hostUID.m_uid)
5149 pSession->hostMigrationInfo.m_newHostAddressValid = true;
5153 else
5155 NetLog("[Host Migration]: received server notification from unknown host " PRFORMAT_UID, PRARG_UID(hostUID));
5159 bool CCryPSNMatchMaking::GetNewHostAddress(char* address, SHostMigrationInfo* pInfo)
5161 bool success = false;
5163 CryLobbySessionHandle sessionIndex = GetSessionHandleFromGameSessionHandle(pInfo->m_session);
5164 SSession* pSession = &m_sessions[sessionIndex];
5165 SHostMigrationInfo_Private* pPrivateInfo = &pSession->hostMigrationInfo;
5167 if ((pSession->localFlags & CRYSESSION_LOCAL_FLAG_USED) && pPrivateInfo->m_newHostAddressValid)
5169 uint32 myIP = 0;
5170 uint16 myPort = 0;
5172 const SSession::SRoomMember* const pMember = FindRoomMemberFromRoomMemberID(sessionIndex, pSession->m_ownerMemberId);
5174 if (pMember)
5176 if (pSession->serverConnectionID != CryMatchMakingInvalidConnectionID)
5178 if (pSession->desiredHostUID != CryMatchMakingInvalidConnectionUID)
5180 if ((pMember->m_valid & ePSNMI_Me) == 0) // Make sure we are not the new host before updating the connection information
5182 if (!pSession->hostMigrationInfo.m_matchMakingFinished)
5184 CryMatchMakingConnectionID remoteConnectionID = FindConnectionIDFromRoomMemberID(sessionIndex, pSession->m_ownerMemberId);
5185 if (remoteConnectionID != CryMatchMakingInvalidConnectionID)
5187 pInfo->SetIsNewHost(false);
5188 success = (pSession->remoteConnection[remoteConnectionID].uid == pSession->desiredHostUID);
5190 NetLog("[Host Migration]: new host for session " PRFORMAT_SH " host uid " PRFORMAT_UID " desired uid " PRFORMAT_UID, PRARG_SH(sessionIndex), PRARG_UID(pSession->remoteConnection[remoteConnectionID].uid), PRARG_UID(pSession->desiredHostUID));
5192 else
5194 NetLog("[Host Migration]: failed to find connection for new host " PRFORMAT_UID " of session " PRFORMAT_SH, PRARG_UID(pSession->desiredHostUID), PRARG_SH(sessionIndex));
5197 else
5199 NetLog("[Host Migration]: matchmaking not finished desiredHostUID " PRFORMAT_UID " newHostUID " PRFORMAT_UID, PRARG_UID(pSession->desiredHostUID), PRARG_UID(pSession->newHostUID));
5203 else
5205 pInfo->SetIsNewHost(true);
5206 success = (pSession->localConnection.uid == pSession->desiredHostUID);
5208 NetLog("[Host Migration]: becoming the new host for session " PRFORMAT_SH " host uid " PRFORMAT_UID " desired uid " PRFORMAT_UID, PRARG_SH(sessionIndex), PRARG_UID(pSession->localConnection.uid), PRARG_UID(pSession->desiredHostUID));
5212 return success;
5215 if (pMember->m_signalingState == ePSNCS_Active)
5217 myIP = pMember->m_peerAddr.s_addr;
5218 myPort = pMember->m_peerPort;
5220 if ((pMember->m_valid & ePSNMI_Me) == 0) // Make sure we are not the new host before updating the connection information
5222 if (!pSession->hostMigrationInfo.m_matchMakingFinished)
5224 pInfo->SetIsNewHost(false);
5225 // Wait until the server has notified us that migration has completed
5226 return false;
5229 NetLog("[Host Migration]: new host is uid %i " PRFORMAT_SH, pSession->m_ownerMemberId, PRARG_SH(sessionIndex));
5230 m_lobby->DecodeAddress(myIP, myPort, address, false);
5232 else
5234 // We are the new host, we should return quickly
5235 pInfo->SetIsNewHost(true);
5236 NetLog("[Host Migration]: becoming the new host for " PRFORMAT_SH "...", PRARG_SH(sessionIndex));
5238 const SCryLobbyParameters& lobbyParams = m_lobby->GetLobbyParameters();
5239 uint16 port = lobbyParams.m_listenPort;
5240 cry_sprintf(address, HOST_MIGRATION_MAX_SERVER_NAME_SIZE, "%s:%d", LOCAL_CONNECTION_STRING, port);
5244 NetLog("[Host Migration]: Using %s as connection address", address);
5245 success = true;
5248 return success;
5251 void CCryPSNMatchMaking::HostMigrationStartNT(CryMatchMakingTaskID mmTaskID)
5253 STask* pTask = &m_task[mmTaskID];
5254 SSession* pSession = &m_sessions[pTask->session];
5256 // Ensure we're the host and we've not started the session
5257 if ((pSession->localFlags & (CRYSESSION_LOCAL_FLAG_HOST | CRYSESSION_LOCAL_FLAG_STARTED)) == CRYSESSION_LOCAL_FLAG_HOST)
5259 // Determine if host hinting has a better host
5260 SHostHintInformation newHost;
5261 CryMatchMakingConnectionID newHostID;
5262 if (FindConnectionFromSessionUID(pTask->session, pSession->newHostUID, &newHostID))
5264 SSession::SRConnection* pConnection = &pSession->remoteConnection[newHostID];
5265 newHost = pConnection->hostHintInfo;
5268 bool isBetterHost = false;
5269 if (SortNewHostPriorities_ComparatorHelper(newHost, pSession->hostHintInfo) < 0)
5271 isBetterHost = true;
5274 if (isBetterHost)
5276 pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT] = m_lobby->MemAlloc(sizeof(SGrantRoomOwnerParamData));
5277 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT] != TMemInvalidHdl)
5279 if (HostMigrationInitiate(pTask->session, eDC_Unknown))
5281 const uint32 maxBufferSize = CryLobbyPacketHeaderSize;
5282 uint8 buffer[maxBufferSize];
5283 CCryLobbyPacket packet;
5285 NetLog("[Host Migration]: local server is not best host for " PRFORMAT_SH "- instructing clients to choose new host (sent from " PRFORMAT_UID ")", PRARG_SH(pTask->session), PRARG_UID(pSession->localConnection.uid));
5286 packet.SetWriteBuffer(buffer, maxBufferSize);
5287 packet.StartWrite(ePSNPT_HostMigrationStart, true);
5289 SendToAll(mmTaskID, &packet, pTask->session, CryMatchMakingInvalidConnectionID);
5290 pSession->localFlags &= ~CRYSESSION_LOCAL_FLAG_HOST;
5292 SGrantRoomOwnerParamData* pGrantRoomOwnerData = (SGrantRoomOwnerParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT]);
5293 memset(pGrantRoomOwnerData, 0, sizeof(SGrantRoomOwnerParamData));
5295 pGrantRoomOwnerData->m_reqParam.roomId = pSession->m_roomId;
5296 pGrantRoomOwnerData->m_reqParam.newOwner = (SceNpMatching2RoomMemberId)(pSession->newHostUID.m_uid);
5298 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
5300 else
5302 NetLog("[Host Migration]: local server is not best host for " PRFORMAT_SH ", but session is not migratable", PRARG_SH(pTask->session));
5303 UpdateTaskError(mmTaskID, eCLE_SessionNotMigratable);
5304 StopTaskRunning(mmTaskID);
5307 else
5309 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
5312 if (pTask->error != eCLE_Success)
5314 StopTaskRunning(mmTaskID);
5317 else
5319 NetLog("[Host Migration]: local server is best host for " PRFORMAT_SH, PRARG_SH(pTask->session));
5320 StopTaskRunning(mmTaskID);
5323 else
5325 if (pSession->localFlags & CRYSESSION_LOCAL_FLAG_STARTED)
5327 NetLog("[Host Migration]: SessionEnsureBestHost() called after the session had started");
5330 StopTaskRunning(mmTaskID);
5334 void CCryPSNMatchMaking::TickHostMigrationStartNT(CryMatchMakingTaskID mmTaskID)
5336 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
5337 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
5339 STask* pTask = &m_task[mmTaskID];
5341 if (pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT] != TMemInvalidHdl)
5343 SGrantRoomOwnerParamData* pGrantRoomOwnerData = (SGrantRoomOwnerParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GRANTROOM_REQUEST_SLOT]);
5345 StartSubTask(eST_WaitingForGrantRoomOwnerRequestCallback, mmTaskID);
5347 int ret = sceNpMatching2GrantRoomOwner(m_pPSNSupport->GetMatchmakingContextId(), &pGrantRoomOwnerData->m_reqParam, NULL, &pTask->m_reqId);
5348 if (ret == PSN_OK)
5350 //-- waiting for callback
5352 else
5354 NetLog("sceNpMatching2GrantRoomOwnerRequest : error %08X", ret);
5355 //-- triggering a PSN error will cause an error event into SupportCallback() and set a task error if it needs to clean up.
5356 //-- otherwise, we have to update the task error ourself.
5357 if (!m_pPSNSupport->HandlePSNError(ret))
5359 UpdateTaskError(mmTaskID, eCLE_InternalError);
5363 else
5365 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
5370 bool CCryPSNMatchMaking::EventRequestResponse_GrantRoomOwner(CCryPSNMatchMaking* _this, STask* pTask, CryMatchMakingTaskID taskId, SCryPSNSupportCallbackEventData& data)
5372 // sanity
5373 assert(pTask->subTask == eST_WaitingForGrantRoomOwnerRequestCallback);
5374 assert(data.m_requestEvent.m_event == REQUEST_EVENT_GRANT_ROOM_OWNER);
5375 assert(data.m_requestEvent.m_dataSize == 0);
5377 // We don't really care if this GrantRoomOwnerRequest succeeds for fails, so we'll just mark the task as complete
5378 _this->UpdateTaskError(taskId, eCLE_Success);
5379 _this->StopTaskRunning(taskId);
5381 // this event is handled
5382 return true;
5385 void CCryPSNMatchMaking::ProcessHostMigrationStart(const TNetAddress& addr, CCrySharedLobbyPacket* pPacket)
5387 CryLobbySessionHandle h = CryLobbyInvalidSessionHandle;
5388 SCryMatchMakingConnectionUID hostUID = pPacket->GetFromConnectionUID();
5389 CryMatchMakingConnectionID mmCxID = CryMatchMakingInvalidConnectionID;
5391 if (FindConnectionFromUID(hostUID, &h, &mmCxID))
5393 SSession* pSession = &m_sessions[h];
5395 NetLog("[Host Migration]: received host migration push event for " PRFORMAT_SHMMCINFO, PRARG_SHMMCINFO(h, mmCxID, pSession->remoteConnection[mmCxID].connectionID, hostUID));
5397 if (pSession->IsUsed() && !(pSession->localFlags & CRYSESSION_LOCAL_FLAG_HOST))
5399 if (pSession->hostMigrationInfo.m_state == eHMS_Idle)
5401 NetLog("[Host Migration]: remote server is not best host for " PRFORMAT_SH " - instructed to choose new host", PRARG_SH(h));
5402 HostMigrationInitiate(h, eDC_Unknown);
5404 else
5406 NetLog("[Host Migration]: ignoring pushed migration event - already migrating " PRFORMAT_SH, PRARG_SH(h));
5410 else
5412 NetLog("[Host Migration]: received push migration event from unknown host " PRFORMAT_UID, PRARG_UID(hostUID));
5415 #endif // NETWORK_HOST_MIGRATION
5417 ECryLobbyError CCryPSNMatchMaking::SessionEnsureBestHost(CrySessionHandle gh, CryLobbyTaskID* pTaskID, CryMatchmakingCallback pCB, void* pCBArg)
5419 ECryLobbyError rc = eCLE_Success;
5421 #if NETWORK_HOST_MIGRATION
5422 LOBBY_AUTO_LOCK;
5424 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
5426 if (h != CryLobbyInvalidSessionHandle)
5428 CryMatchMakingTaskID mmTaskID;
5429 SSession* pSession = &m_sessions[h];
5430 rc = StartTask(eT_SessionMigrateHostStart, false, pSession->localConnection.users[0], &mmTaskID, pTaskID, h, (void*)pCB, pCBArg);
5432 if (rc == eCLE_Success)
5434 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
5437 #endif
5439 return rc;
5442 void CCryPSNMatchMaking::AddVoiceUser(SSession::SRoomMember* pMember)
5444 #if USE_PSN_VOICE
5445 CCryPSNVoice* pVoice = (CCryPSNVoice*)m_pService->GetVoice();
5446 if (pVoice)
5448 assert(pMember->IsValid(ePSNMI_Other));
5449 pVoice->AddRemoteTalker(pMember->m_npId, pMember->m_peerAddr, pMember->m_peerPort, (pMember->m_signalingState == ePSNCS_Active) ? true : false);
5451 #endif // USE_PSN_VOICE
5454 void CCryPSNMatchMaking::ClearVoiceUser(SSession::SRoomMember* pMember)
5456 #if USE_PSN_VOICE
5457 CCryPSNVoice* pVoice = (CCryPSNVoice*)m_pService->GetVoice();
5458 if (pVoice)
5460 assert(pMember->m_valid & ePSNMI_Other);
5461 pVoice->ClearRemoteTalker(pMember->m_npId);
5463 #endif // USE_PSN_VOICE
5466 void CCryPSNMatchMaking::UpdateVoiceUsers()
5468 #if USE_PSN_VOICE
5469 CCryPSNVoice* pVoice = (CCryPSNVoice*)m_pService->GetVoice();
5470 if (pVoice)
5472 bool bNeedsVoice = false;
5474 for (uint32 i = 0; ((i < MAX_MATCHMAKING_SESSIONS) && (bNeedsVoice == false)); i++)
5476 SSession* pSession = &m_sessions[i];
5477 if (pSession->IsUsed())
5479 for (uint32 j = 0; j < MAX_PSN_ROOM_MEMBERS; j++)
5481 SSession::SRoomMember* pMember = &pSession->m_members[j];
5482 if (pMember->IsValid(ePSNMI_Other))
5484 bNeedsVoice = true;
5485 break;
5491 if (bNeedsVoice && !m_pPSNSupport->IsChatRestricted())
5493 pVoice->Activate();
5495 else
5497 pVoice->Deactivate();
5500 #endif //USE_PSN_VOICE
5503 ECryLobbyError CCryPSNMatchMaking::CopySessionIDToBuffer(CrySessionID sessionId, void* pBuffer, size_t& bufferSize)
5505 if (SCryPSNSessionID* pData = (SCryPSNSessionID*)sessionId.get())
5507 size_t requiredSize = sizeof(SCryPSNSessionID);
5508 if (bufferSize >= requiredSize)
5510 memcpy(pBuffer, pData, requiredSize);
5511 bufferSize = requiredSize;
5512 return eCLE_Success;
5514 else
5516 return eCLE_OutOfMemory;
5519 return eCLE_InvalidSession;
5522 ECryLobbyError CCryPSNMatchMaking::CopySessionIDFromBuffer(const void* pBuffer, size_t bufferSize, CrySessionID& sessionId)
5524 size_t requiredSize = sizeof(SCryPSNSessionID);
5525 if (bufferSize == requiredSize)
5527 SCryPSNSessionID* pData = new SCryPSNSessionID();
5528 // cppcheck-suppress memsetClass (if used in conjunction with CopySessionIDToBuffer(), this is ok)
5529 memcpy(pData, pBuffer, requiredSize);
5530 sessionId = pData;
5531 return eCLE_Success;
5533 return eCLE_InvalidParam;
5536 void CCryPSNMatchMaking::ForceFromInvite(CrySessionID sessionId)
5538 if (SCryPSNSessionID* pData = (SCryPSNSessionID*)sessionId.get())
5540 pData->m_fromInvite = true;
5544 ECryLobbyError CCryPSNMatchMaking::SessionSetAdvertisementData(CrySessionHandle gh, uint8* pData, uint32 dataSize, CryLobbyTaskID* pTaskID, CryMatchmakingCallback pCb, void* pCbArg)
5546 LOBBY_AUTO_LOCK;
5548 ECryLobbyError rc = eCLE_InvalidSession;
5549 CryLobbySessionHandle h = GetSessionHandleFromGameSessionHandle(gh);
5550 if (h != CryLobbyInvalidSessionHandle)
5552 CryMatchMakingTaskID mmTaskID;
5553 SSession* pSession = &m_sessions[h];
5554 rc = StartTask(eT_SessionSetAdvertisementData, false, 0, &mmTaskID, pTaskID, h, (void*)pCb, pCbArg);
5555 if (rc == eCLE_Success)
5557 rc = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT, NULL, 1, sizeof(SUpdateAdvertisementDataParamData));
5558 if (rc == eCLE_Success)
5560 rc = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT, NULL, 1, sizeof(SCryPSNOrbisWebApiUpdateSessionInput));
5561 if (rc == eCLE_Success)
5563 SCryPSNOrbisWebApiUpdateSessionInput* pAdvertInput = (SCryPSNOrbisWebApiUpdateSessionInput*)m_lobby->MemGetPtr(m_task[mmTaskID].params[PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT]);
5564 memset(pAdvertInput, 0, sizeof(SCryPSNOrbisWebApiUpdateSessionInput));
5566 memcpy(&pAdvertInput->sessionId, &pSession->m_sessionId, sizeof(SceNpSessionId));
5568 pAdvertInput->advertisement.m_pData = pAdvertInput->data;
5569 pAdvertInput->advertisement.m_sizeofData = MIN(dataSize, CRY_WEBAPI_UPDATESESSION_LINKDATA_MAX_SIZE);
5570 memcpy(pAdvertInput->data, pData, pAdvertInput->advertisement.m_sizeofData);
5572 SConfigurationParams neededInfo = {
5573 CLCC_PSN_UPDATE_SESSION_ADVERTISEMENT, { NULL }
5575 neededInfo.m_pData = (void*)&pAdvertInput->advertisement;
5576 m_lobby->GetConfigurationInformation(&neededInfo, 1);
5578 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
5580 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
5584 if (rc != eCLE_Success)
5586 FreeTask(mmTaskID);
5591 return rc;
5594 void CCryPSNMatchMaking::TickSessionSetAdvertisementData(CryMatchMakingTaskID mmTaskID)
5596 STask* pTask = &m_task[mmTaskID];
5598 if (pTask->error == eCLE_Success)
5600 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
5601 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
5603 if ((pTask->params[PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT] != TMemInvalidHdl) &&
5604 (pTask->params[PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT] != TMemInvalidHdl))
5606 SUpdateAdvertisementDataParamData* pParam = (SUpdateAdvertisementDataParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_UPDATEADVERT_REQUEST_SLOT]);
5608 StartSubTask(eST_WaitingForUpdateAdvertisementDataWebApiCallback, mmTaskID);
5610 pParam->m_jobId = m_pPSNSupport->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::UpdateSession, pTask->params[PSN_MATCHMAKING_WEBAPI_UPDATEADVERT_REQUEST_SLOT]);
5611 if (pParam->m_jobId != INVALID_WEBAPI_JOB_ID)
5613 //-- waiting for callback
5615 else
5617 // error - didn't add webapi job
5618 UpdateTaskError(mmTaskID, eCLE_InternalError);
5621 else
5623 // error - bad param slots
5624 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
5629 if ((pTask->error != eCLE_Success) || pTask->canceled)
5631 StopTaskRunning(mmTaskID);
5635 void CCryPSNMatchMaking::EventWebApiUpdateSessionAdvertisement(CryMatchMakingTaskID mmTaskID, SCryPSNSupportCallbackEventData& data)
5637 STask* pTask = &m_task[mmTaskID];
5639 if (pTask->session != CryLobbyInvalidSessionHandle)
5641 if (data.m_webApiEvent.m_error == PSN_OK)
5643 // not expecting a response body, just mark task successful and stop
5644 UpdateTaskError(mmTaskID, eCLE_Success);
5645 StopTaskRunning(mmTaskID);
5646 return;
5650 // something went wrong
5651 UpdateTaskError(mmTaskID, eCLE_InternalError);
5652 StopTaskRunning(mmTaskID);
5655 void CCryPSNMatchMaking::EndSessionSetAdvertisementData(CryMatchMakingTaskID mmTaskID)
5657 STask* pTask = &m_task[mmTaskID];
5658 ((CryMatchmakingCallback)pTask->cb)(pTask->lTaskID, pTask->error, pTask->cbArg);
5661 ECryLobbyError CCryPSNMatchMaking::SessionGetAdvertisementData(CrySessionID sessionId, CryLobbyTaskID* pTaskID, CryMatchmakingSessionGetAdvertisementDataCallback pCb, void* pCbArg)
5663 LOBBY_AUTO_LOCK;
5665 ECryLobbyError rc = eCLE_InvalidSession;
5666 if (sessionId != CrySessionInvalidID)
5668 CryMatchMakingTaskID mmTaskID;
5669 rc = StartTask(eT_SessionGetAdvertisementData, false, 0, &mmTaskID, pTaskID, CryLobbyInvalidSessionHandle, (void*)pCb, pCbArg);
5670 if (rc == eCLE_Success)
5672 rc = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT, NULL, 1, sizeof(SGetAdvertisementDataParamData));
5673 if (rc == eCLE_Success)
5675 rc = CreateTaskParam(mmTaskID, PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT, NULL, 1, sizeof(SCryPSNOrbisWebApiGetSessionLinkDataInput));
5676 if (rc == eCLE_Success)
5678 SCryPSNSessionID* pPSNSessionId = (SCryPSNSessionID*)sessionId.get();
5679 SCryPSNOrbisWebApiGetSessionLinkDataInput* pAdvertInput = (SCryPSNOrbisWebApiGetSessionLinkDataInput*)m_lobby->MemGetPtr(m_task[mmTaskID].params[PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT]);
5680 memcpy(&pAdvertInput->sessionId, &pPSNSessionId->m_sessionId, sizeof(SceNpSessionId));
5682 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
5684 FROM_GAME_TO_LOBBY(&CCryPSNMatchMaking::StartTaskRunning, this, mmTaskID);
5688 if (rc != eCLE_Success)
5690 FreeTask(mmTaskID);
5695 NetLog("[Lobby] Start SessionGetAdvertisementData error %d", rc);
5696 return rc;
5699 void CCryPSNMatchMaking::TickSessionGetAdvertisementData(CryMatchMakingTaskID mmTaskID)
5701 STask* pTask = &m_task[mmTaskID];
5703 if (pTask->error == eCLE_Success)
5705 m_pPSNSupport->ResumeTransitioning(ePSNOS_Matchmaking_Available);
5706 if (m_pPSNSupport->HasTransitioningReachedState(ePSNOS_Matchmaking_Available))
5708 if ((pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT] != TMemInvalidHdl) &&
5709 (pTask->params[PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT] != TMemInvalidHdl))
5711 SGetAdvertisementDataParamData* pParam = (SGetAdvertisementDataParamData*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_PSNSUPPORT_GETADVERT_REQUEST_SLOT]);
5713 StartSubTask(eST_WaitingForGetAdvertisementDataWebApiCallback, mmTaskID);
5715 pParam->m_jobId = m_pPSNSupport->GetWebApiInterface().AddJob(CCryPSNOrbisWebApiThread::GetSessionLinkData, pTask->params[PSN_MATCHMAKING_WEBAPI_GETADVERT_REQUEST_SLOT]);
5716 if (pParam->m_jobId != INVALID_WEBAPI_JOB_ID)
5718 //-- waiting for callback
5720 else
5722 // error - didnt queue webapi job
5723 UpdateTaskError(mmTaskID, eCLE_InternalError);
5726 else
5728 // error - no slots allocated
5729 UpdateTaskError(mmTaskID, eCLE_OutOfMemory);
5734 if ((pTask->error != eCLE_Success) || pTask->canceled)
5736 StopTaskRunning(mmTaskID);
5740 void CCryPSNMatchMaking::EventWebApiGetSessionLinkData(CryMatchMakingTaskID mmTaskID, SCryPSNSupportCallbackEventData& data)
5742 STask* pTask = &m_task[mmTaskID];
5744 if (data.m_webApiEvent.m_error == PSN_OK)
5746 if (data.m_webApiEvent.m_pResponseBody)
5748 if ((data.m_webApiEvent.m_pResponseBody->eType == SCryPSNWebApiResponseBody::E_RAW) &&
5749 (data.m_webApiEvent.m_pResponseBody->rawResponseBodyHdl != TMemInvalidHdl) &&
5750 (data.m_webApiEvent.m_pResponseBody->rawResponseBodySize > 0))
5752 // success.
5753 pTask->params[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT] = data.m_webApiEvent.m_pResponseBody->rawResponseBodyHdl;
5754 pTask->numParams[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT] = (uint32)data.m_webApiEvent.m_pResponseBody->rawResponseBodySize;
5756 // We don't want the data to be deleted when this function returns since we copied the handle.
5757 // If we invalidate the handle, it won't be deleted when the event is cleared up.
5758 data.m_webApiEvent.m_pResponseBody->rawResponseBodyHdl = TMemInvalidHdl;
5759 data.m_webApiEvent.m_pResponseBody->rawResponseBodySize = 0;
5761 UpdateTaskError(mmTaskID, eCLE_Success);
5762 StopTaskRunning(mmTaskID);
5763 return;
5768 // something went wrong
5769 UpdateTaskError(mmTaskID, eCLE_InternalError);
5770 StopTaskRunning(mmTaskID);
5773 void CCryPSNMatchMaking::EndSessionGetAdvertisementData(CryMatchMakingTaskID mmTaskID)
5775 uint8* pData = NULL;
5776 uint32 dataSize = 0;
5778 STask* pTask = &m_task[mmTaskID];
5779 if (pTask->error == eCLE_Success)
5781 pData = (uint8*)m_lobby->MemGetPtr(pTask->params[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT]);
5782 dataSize = pTask->numParams[PSN_MATCHMAKING_WEBAPI_GETADVERT_RESPONSE_SLOT];
5785 ((CryMatchmakingSessionGetAdvertisementDataCallback)pTask->cb)(pTask->lTaskID, pTask->error, pData, dataSize, pTask->cbArg);
5788 #endif // USE_CRY_MATCHMAKING
5789 #endif // USE_PSN
5790 #endif // CRY_PLATFORM_ORBIS