nsresult PresentationService::HandleTerminateRequest(nsIPresentationTerminateRequest* aRequest) { nsCOMPtr<nsIPresentationControlChannel> ctrlChannel; nsresult rv = aRequest->GetControlChannel(getter_AddRefs(ctrlChannel)); if (NS_WARN_IF(NS_FAILED(rv) || !ctrlChannel)) { return rv; } nsAutoString sessionId; rv = aRequest->GetPresentationId(sessionId); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } nsCOMPtr<nsIPresentationDevice> device; rv = aRequest->GetDevice(getter_AddRefs(device)); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } bool isFromReceiver; rv = aRequest->GetIsFromReceiver(&isFromReceiver); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } RefPtr<PresentationSessionInfo> info; if (!isFromReceiver) { info = GetSessionInfo(sessionId, nsIPresentationService::ROLE_RECEIVER); } else { info = GetSessionInfo(sessionId, nsIPresentationService::ROLE_CONTROLLER); } if (NS_WARN_IF(!info)) { // Cannot terminate non-existed session. ctrlChannel->Disconnect(NS_ERROR_DOM_OPERATION_ERR); return NS_ERROR_DOM_ABORT_ERR; } // Check if terminate request comes from known device. RefPtr<nsIPresentationDevice> knownDevice = info->GetDevice(); if (NS_WARN_IF(!IsSameDevice(device, knownDevice))) { ctrlChannel->Disconnect(NS_ERROR_DOM_OPERATION_ERR); return NS_ERROR_DOM_ABORT_ERR; } PRES_DEBUG("handle termination:id[%s], receiver[%d]\n", __func__, sessionId.get(), isFromReceiver); return info->OnTerminate(ctrlChannel); }
NS_IMETHODIMP PresentationService::RegisterSessionListener(const nsAString& aSessionId, uint8_t aRole, nsIPresentationSessionListener* aListener) { PRES_DEBUG("%s:id[%s], role[%d]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get(), aRole); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aListener); MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || aRole == nsIPresentationService::ROLE_RECEIVER); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { // Notify the listener of TERMINATED since no correspondent session info is // available possibly due to establishment failure. This would be useful at // the receiver side, since a presentation session is created at beginning // and here is the place to realize the underlying establishment fails. nsresult rv = aListener->NotifyStateChange(aSessionId, nsIPresentationSessionListener::STATE_TERMINATED, NS_ERROR_NOT_AVAILABLE); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_ERROR_NOT_AVAILABLE; } return info->SetListener(aListener); }
NS_IMETHODIMP PresentationService::ReconnectSession(const nsTArray<nsString>& aUrls, const nsAString& aSessionId, uint8_t aRole, nsIPresentationServiceCallback* aCallback) { PRES_DEBUG("%s:id[%s]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get()); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); MOZ_ASSERT(aCallback); MOZ_ASSERT(!aUrls.IsEmpty()); if (aRole != nsIPresentationService::ROLE_CONTROLLER) { MOZ_ASSERT(false, "Only controller can call ReconnectSession."); return NS_ERROR_INVALID_ARG; } if (NS_WARN_IF(!aCallback)) { return NS_ERROR_INVALID_ARG; } RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return aCallback->NotifyError(NS_ERROR_DOM_NOT_FOUND_ERR); } if (NS_WARN_IF(!aUrls.Contains(info->GetUrl()))) { return aCallback->NotifyError(NS_ERROR_DOM_NOT_FOUND_ERR); } return static_cast<PresentationControllingInfo*>(info.get())->Reconnect(aCallback); }
NS_IMETHODIMP PresentationService::CloseSession(const nsAString& aSessionId, uint8_t aRole, uint8_t aClosedReason) { PRES_DEBUG("%s:id[%s], reason[%x], role[%d]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get(), aClosedReason, aRole); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || aRole == nsIPresentationService::ROLE_RECEIVER); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } if (aClosedReason == nsIPresentationService::CLOSED_REASON_WENTAWAY) { // Remove nsIPresentationSessionListener since we don't want to dispatch // PresentationConnectionCloseEvent if the page is went away. info->SetListener(nullptr); } return info->Close(NS_OK, nsIPresentationSessionListener::STATE_CLOSED); }
NS_IMETHODIMP PresentationService::NotifyReceiverReady( const nsAString& aSessionId, uint64_t aWindowId, bool aIsLoading, nsIPresentationTransportBuilderConstructor* aBuilderConstructor) { PRES_DEBUG("%s:id[%s], windowId[%" PRIu64 "], loading[%d]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get(), aWindowId, aIsLoading); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, nsIPresentationService::ROLE_RECEIVER); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } AddRespondingSessionId(aWindowId, aSessionId, nsIPresentationService::ROLE_RECEIVER); if (!aIsLoading) { return static_cast<PresentationPresentingInfo*>(info.get()) ->NotifyResponderFailure(); } nsCOMPtr<nsIPresentationRespondingListener> listener; if (mRespondingListeners.Get(aWindowId, getter_AddRefs(listener))) { nsresult rv = listener->NotifySessionConnect(aWindowId, aSessionId); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } info->SetTransportBuilderConstructor(aBuilderConstructor); return static_cast<PresentationPresentingInfo*>(info.get()) ->NotifyResponderReady(); }
bool PresentationService::IsSessionAccessible(const nsAString& aSessionId, const uint8_t aRole, base::ProcessId aProcessId) { MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || aRole == nsIPresentationService::ROLE_RECEIVER); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return false; } return info->IsAccessible(aProcessId); }
nsresult PresentationService::HandleReconnectRequest(nsIPresentationSessionRequest* aRequest) { nsCOMPtr<nsIPresentationControlChannel> ctrlChannel; nsresult rv = aRequest->GetControlChannel(getter_AddRefs(ctrlChannel)); if (NS_WARN_IF(NS_FAILED(rv) || !ctrlChannel)) { return rv; } nsAutoString sessionId; rv = aRequest->GetPresentationId(sessionId); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } uint64_t windowId; rv = GetWindowIdBySessionIdInternal(sessionId, nsIPresentationService::ROLE_RECEIVER, &windowId); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } RefPtr<PresentationSessionInfo> info = GetSessionInfo(sessionId, nsIPresentationService::ROLE_RECEIVER); if (NS_WARN_IF(!info)) { // Cannot reconnect non-existed session ctrlChannel->Disconnect(NS_ERROR_DOM_OPERATION_ERR); return NS_ERROR_DOM_ABORT_ERR; } nsAutoString url; rv = aRequest->GetUrl(url); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } // Make sure the url is the same as the previous one. if (NS_WARN_IF(!info->GetUrl().Equals(url))) { ctrlChannel->Disconnect(rv); return rv; } return HandleSessionRequest(aRequest); }
NS_IMETHODIMP PresentationService::SendSessionBlob(const nsAString& aSessionId, uint8_t aRole, Blob* aBlob) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || aRole == nsIPresentationService::ROLE_RECEIVER); MOZ_ASSERT(aBlob); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return info->SendBlob(aBlob); }
NS_IMETHODIMP PresentationService::TerminateSession(const nsAString& aSessionId, uint8_t aRole) { PRES_DEBUG("%s:id[%s], role[%d]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get(), aRole); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || aRole == nsIPresentationService::ROLE_RECEIVER); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return info->Close(NS_OK, nsIPresentationSessionListener::STATE_TERMINATED); }
NS_IMETHODIMP PresentationService::BuildTransport(const nsAString& aSessionId, uint8_t aRole) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); if (aRole != nsIPresentationService::ROLE_CONTROLLER) { MOZ_ASSERT(false, "Only controller can call BuildTransport."); return NS_ERROR_INVALID_ARG; } RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return static_cast<PresentationControllingInfo*>(info.get())->BuildTransport(); }
nsresult PresentationService::NotifyTransportClosed(const nsAString& aSessionId, uint8_t aRole, nsresult aReason) { PRES_DEBUG("%s:id[%s], reason[%" PRIx32 "], role[%d]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get(), static_cast<uint32_t>(aReason), aRole); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || aRole == nsIPresentationService::ROLE_RECEIVER); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return info->NotifyTransportClosed(aReason); }
NS_IMETHODIMP PresentationService::UnregisterSessionListener(const nsAString& aSessionId, uint8_t aRole) { PRES_DEBUG("%s:id[%s], role[%d]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get(), aRole); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || aRole == nsIPresentationService::ROLE_RECEIVER); RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (info) { // When content side decide not handling this session anymore, simply // close the connection. Session info is kept for reconnection. Unused << NS_WARN_IF(NS_FAILED(info->Close(NS_OK, nsIPresentationSessionListener::STATE_CLOSED))); return info->SetListener(nullptr); } return NS_OK; }
//============================================================================== // OnEnumerationResponse() // // Handles host enumeration responses, and connects to the returned session. //============================================================================== void CDarkPeer::OnEnumerationResponse(PDPNMSG_ENUM_HOSTS_RESPONSE pEnumHostsResponseMsg) { #if (GAME == GAME_THIEF || GAME == GAME_DROMED) if (!g_ConnectAttempt.IsActive()) { return; } #endif HRESULT hRes; const DPN_APPLICATION_DESC* pAppDesc = pEnumHostsResponseMsg->pApplicationDescription; #if (GAME == GAME_THIEF || GAME == GAME_DROMED) m_pSessionMgr->SetSessionInfo(pEnumHostsResponseMsg->pApplicationDescription); const SessionInfo& info = GetSessionInfo(); if (info.build != TMP_BUILD) { ConPrintF("Server version (%d) does not match client version. Connection failed.", info.build); CancelEnumeration(); return; } NString sessName = pEnumHostsResponseMsg->pApplicationDescription->pwszSessionName; ConPrintF("Game found: %s Players: %d/%d Build: %d.", sessName.Str(), pAppDesc->dwCurrentPlayers, pAppDesc->dwMaxPlayers, info.build); #endif hRes = SetPlayerInfo(); if (FAILED(hRes)) return Log.Print("Failed to set peer info."); // Set the password, if we have one if (g_ConnectAttempt.GetPassword()) { (WCHAR*)pAppDesc->pwszPassword = (WCHAR*)g_ConnectAttempt.GetPassword(); } hRes = m_pDP->Connect(pAppDesc, pEnumHostsResponseMsg->pAddressSender, pEnumHostsResponseMsg->pAddressDevice, NULL, NULL, NULL, 0, this, NULL, NULL, DPNCONNECT_SYNC); g_ConnectAttempt.Clear(); switch (hRes) { case DPN_OK: #ifdef ALLOW_LATE_JOINS if (info.gameStarted) { g_bNeedSnapshot = true; CNetMsg_RequestSnapshot msg; DbgPrint("Requesting snapshot"); g_pNetMan->m_numStartedSynch = g_pNetMan->NumPlayers(); // 8/8/10 //g_pDarkNet->GetSessionManager()->GetApplicationDesc()->dwCurrentPlayers - 1; DbgPrint("Other players: %d", g_pNetMan->m_numStartedSynch); cNetManagerFns::_LoopFunc((void*)0x006C9420, kMsgBeginFrame, NULL); SendToHost((void*)&msg, sizeof(CNetMsg_RequestSnapshot), DPNSEND_GUARANTEED); } #endif break; // Connection successful case DPNERR_INVALIDPASSWORD: ConPrintF("Incorrect password."); CancelEnumeration(); break; case DPNERR_SESSIONFULL: ConPrintF("The server is full."); CancelEnumeration(); break; case DPNERR_HOSTREJECTEDCONNECTION: ConPrintF("Cannot join server: the host has already started the mission."); CancelEnumeration(); break; default: ConPrintF("Failed to connect to server. (%x)", DPlayErrorToString(hRes)); // Unknown error CancelEnumeration(); } }
nsresult PresentationService::HandleSessionRequest(nsIPresentationSessionRequest* aRequest) { nsCOMPtr<nsIPresentationControlChannel> ctrlChannel; nsresult rv = aRequest->GetControlChannel(getter_AddRefs(ctrlChannel)); if (NS_WARN_IF(NS_FAILED(rv) || !ctrlChannel)) { return rv; } nsAutoString url; rv = aRequest->GetUrl(url); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } nsAutoString sessionId; rv = aRequest->GetPresentationId(sessionId); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } nsCOMPtr<nsIPresentationDevice> device; rv = aRequest->GetDevice(getter_AddRefs(device)); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } // Create or reuse session info. RefPtr<PresentationSessionInfo> info = GetSessionInfo(sessionId, nsIPresentationService::ROLE_RECEIVER); // This is the case for reconnecting a session. // Update the control channel and device of the session info. // Call |NotifyResponderReady| to indicate the receiver page is already there. if (info) { PRES_DEBUG("handle reconnection:id[%s]\n", NS_ConvertUTF16toUTF8(sessionId).get()); info->SetControlChannel(ctrlChannel); info->SetDevice(device); return static_cast<PresentationPresentingInfo*>( info.get())->DoReconnect(); } // This is the case for a new session. PRES_DEBUG("handle new session:url[%d], id[%s]\n", NS_ConvertUTF16toUTF8(url).get(), NS_ConvertUTF16toUTF8(sessionId).get()); info = new PresentationPresentingInfo(url, sessionId, device); rv = info->Init(ctrlChannel); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return rv; } mSessionInfoAtReceiver.Put(sessionId, info); // Notify the receiver to launch. nsCOMPtr<nsIPresentationRequestUIGlue> glue = do_CreateInstance(PRESENTATION_REQUEST_UI_GLUE_CONTRACTID); if (NS_WARN_IF(!glue)) { ctrlChannel->Disconnect(NS_ERROR_DOM_OPERATION_ERR); return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR); } nsCOMPtr<nsISupports> promise; rv = glue->SendRequest(url, sessionId, device, getter_AddRefs(promise)); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Disconnect(rv); return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR); } nsCOMPtr<Promise> realPromise = do_QueryInterface(promise); static_cast<PresentationPresentingInfo*>(info.get())->SetPromise(realPromise); return NS_OK; }