Example #1
0
XSessionImplPtr SessionServer::CreateNewSession(const std::string& sessionName, SessionType type)
{
    XSessionImplPtr xsession;
	uint16 sessionPort;

    // Better way to check for error?
    if (m_portPool->GetPort(sessionPort))
    {
        uint32 id = GetNewSessionId();

        xsession = new XSessionImpl(sessionName, sessionPort, type, id);

		// Check that the session was able to set itself up, open a socket to listen on, etc
		for (int creationCount = 0; !xsession->IsInitialized() && creationCount < 10; ++creationCount)
		{
			m_portPool->ReleasePort(sessionPort);

			if (m_portPool->GetPort(sessionPort))
			{
				xsession = new XSessionImpl(sessionName, sessionPort, type, id);
			}
			else
			{
				break;
			}
		}

		if (xsession->IsInitialized())
		{
			m_sessionChangeListener[xsession] = xsession->RegisterCallback(this);
			m_sessions.push_back(xsession);
			LogInfo("Created Session \"%s\" with ID %u on port %i", sessionName.c_str(), id, sessionPort);

			// Notify the listeners about the new session
			for (size_t i = 0; i < m_clients.size(); ++i)
			{
				SessionAddedMsg sessionAddedMsg;
				sessionAddedMsg.SetSessionDescriptor(xsession->GetSessionDescription(m_clients[i].m_connection->GetSocket()));

				NetworkOutMessagePtr msg = m_clients[i].m_connection->CreateMessage((byte)MessageID::SessionControl);
				msg->Write(sessionAddedMsg.ToJSONString());

				m_clients[i].m_connection->Send(msg, MessagePriority::Medium, MessageReliability::ReliableOrdered, MessageChannel::Default, true);
			}
		}
		else
		{
			LogError("Failed to create new session %s", sessionName.c_str());
			xsession = NULL;
		}
    }

    return xsession;
}
void UserPresenceManagerLeaderImpl::PushPresenceUpdate()
{
    // Tell any connected baraboo about the new mute state.
    if (m_barabooConnection->IsConnected())
    {
        NetworkOutMessagePtr message = m_barabooConnection->CreateMessage(MessageID::UserPresenceChange);
        message->Write(m_localUser ? m_localUser->GetName() : NULL);
        message->Write(int32((m_localUser && m_localUser->GetMuteState()) ? 1 : 0));
        m_barabooConnection->Send(message);
    }

    UpdateListeners();
}
Example #3
0
void SessionServer::SendSessionMessageToAllClients(const std::string& message)
{
	NetworkOutMessagePtr msg = m_messagePool->AcquireMessage();
	msg->Write((byte)MessageID::SessionControl);
	msg->Write(message);

	for (size_t i = 0; i < m_clients.size(); ++i)
	{
		m_clients[i].m_connection->Send(msg, MessagePriority::Medium, MessageReliability::ReliableOrdered, MessageChannel::Default, false);
	}

	m_messagePool->ReturnMessage(msg);
}
void SessionImpl::UpdateUser(const UserPtr& updatedUser)
{
    // Expect this only to be called on sessions we are joined to.
    XTASSERT(IsJoined());

    UserPtr user = FindUser(updatedUser->GetID());

    // Assert that we aren't updating for a user who's not present.
    if (XTVERIFY(user))
    {
        UserChangedSessionMsg userUpdateMsg(m_id, user->GetName()->GetString(), user->GetID(), user->GetMuteState());
        NetworkOutMessagePtr msg = m_sessionConnection->CreateMessage(MessageID::SessionControl);
        
        msg->Write(new XString(userUpdateMsg.ToJSONString()));
        m_sessionConnection->Send(msg);
    }
}
void SessionImpl::OnConnected(const NetworkConnectionPtr& connection)
{
	// We have successfully connected to this session.  
	// Now send it information about us so it lets us in all the way

	XTASSERT(m_curState == MachineSessionState::JOINING);

	JoinSessionRequest request(
		m_context->GetLocalUser()->GetName()->GetString(),
		m_context->GetLocalUser()->GetID(),
        m_context->GetLocalUser()->GetMuteState()
		);

	NetworkOutMessagePtr msg = connection->CreateMessage(MessageID::SessionControl);

	msg->Write(new XString(request.ToJSONString()));

	connection->Send(msg);
}
Example #6
0
void SessionServer::OnListSessionsRequest(const ListSessionsRequest&, const NetworkConnectionPtr& connection)
{
	// Fill in a message with a list of all the sessions and send it

	ListSessionsReply reply;

	reply.SetSessionCount(static_cast<int32>(m_sessions.size()));

	for (size_t i = 0; i < m_sessions.size(); ++i)
	{
		XSessionImplPtr currentSession = m_sessions[i];

		reply.SetSessionDescriptor((int32)i, currentSession->GetSessionDescription(connection->GetSocket()));
	}

	NetworkOutMessagePtr msg = connection->CreateMessage(MessageID::SessionControl);
	msg->Write(reply.ToJSONString());

	connection->Send(msg);
}
void SendToForwarder::OnMessageReceived(const NetworkConnectionPtr& connection, NetworkInMessage& message)
{
	const byte* inMsg = message.GetData();
	const uint32 inMsgSize = message.GetSize();

	// Get the sendto header
	const SendToNetworkHeader* sendToHeader = reinterpret_cast<const SendToNetworkHeader*>(inMsg);

	// Extract the payload from the sendto message and put in a new outgoing message
	const byte* payload = inMsg + sizeof(SendToNetworkHeader);
	const uint32 payloadSize = inMsgSize - sizeof(SendToNetworkHeader);

	if (payloadSize > 0)
	{
		NetworkOutMessagePtr outMsg = connection->CreateMessage(*payload);
		outMsg->WriteArray(payload + 1, payloadSize - 1);

		// Send the payload to the correct remote peer
		auto userConnectionItr = m_connections.find(sendToHeader->m_userID);
		if (userConnectionItr != m_connections.end())
		{
			ClientRole role = sendToHeader->m_deviceRole;

			if (role == ClientRole::Primary ||
				role == ClientRole::Unspecified)
			{
				// Forward the message on with the same settings that it was sent here with
				userConnectionItr->second.m_primaryConnection ->Send(outMsg, sendToHeader->m_priority, sendToHeader->m_reliability, sendToHeader->m_channel, false);
			}

			if (role == ClientRole::Secondary ||
				role == ClientRole::Unspecified)
			{
				// Forward the message on with the same settings that it was sent here with
				userConnectionItr->second.m_secondaryConnection->Send(outMsg, sendToHeader->m_priority, sendToHeader->m_reliability, sendToHeader->m_channel, false);
			}
		}

		connection->ReturnMessage(outMsg);
	}
}
void SyncManagerImpl::SendSyncMessage(RemoteSyncPeer& remotePeer)
{
	if (remotePeer.m_bHandshakeComplete)
	{
		// If our list of ops to send is empty, and we have more than 2 ops that we have not acknowledged,
		// send a noop so the remote machine can release its outgoing queue and save some memory
		if (remotePeer.m_sendList.empty() && 
			remotePeer.m_lastAcknowledgedVersion < remotePeer.m_localState.m_opsReceived)
		{
			VersionedOp op;
			op.m_op = new AckOperation(AuthorityLevel::Unknown);
			op.m_state = remotePeer.m_localState;
			remotePeer.m_sendList.push_back(op);
		}

		if (!remotePeer.m_sendList.empty()) // We have ops to send
		{
#if defined(SYNC_DEBUG)
			LogInfo("Sending messages to %s", remotePeer.m_userName.c_str());
#endif

			NetworkOutMessagePtr msg = remotePeer.m_connection->CreateMessage(m_messageID);

			// Add the sub-type of the message
			msg->Write((byte)SyncChanges);

			// Write out the number of ops sent in this message
			msg->Write((int32)remotePeer.m_sendList.size());

			// Write out each of the ops
			for (VersionedOpList::iterator it = remotePeer.m_sendList.begin(); it != remotePeer.m_sendList.end(); ++it)
			{
				VersionedOp& currentOp = *it;

#if defined(SYNC_DEBUG)
				LogInfo(" - %s, version %i %i", currentOp.m_op->GetOpDescription().c_str(), currentOp.m_state.m_opsSent, currentOp.m_state.m_opsReceived);
#endif

				// Add our view of the messages sent and received
				msg->Write(currentOp.m_state.m_opsSent);
				msg->Write(currentOp.m_state.m_opsReceived);

				// Write the type of the op
				msg->Write((byte)currentOp.m_op->GetType());

				// Write the op data
				currentOp.m_op->Serialize(msg);

				// Record that we have acknowledged all the messages received
				remotePeer.m_lastAcknowledgedVersion = currentOp.m_state.m_opsReceived;
			}

			// Send the message
			remotePeer.m_connection->Send(msg);

			remotePeer.m_sendList.clear();
		}
	}
}
void CreateOperation::Serialize(const NetworkOutMessagePtr& msg) const
{
	msg->Write((byte)m_elementType);
	msg->Write(m_name);
	msg->Write(m_elementGuid);
	msg->Write(m_parentGuid);
	m_startingValue.Serialize(msg);

	// Write the number of ancestors
	msg->Write(static_cast<uint32>(m_hierarchy.size()));

	// Write the GUIDs of the ancestors
	for (size_t i = 0; i < m_hierarchy.size(); ++i)
	{
		msg->Write(m_hierarchy[i]);
	}

	// NOTE: authority level is NOT included in the op when serialized; it changes as the op is sent around the network
}
void SyncManagerImpl::SendHandshakeMessage(RemoteSyncPeer& remotePeer)
{
#if defined(SYNC_DEBUG)
	LogInfo("%s Sending Handshake", m_syncContext->GetLocalUser()->GetName().GetString().c_str());
#endif

	// We should not be sending a handshake message if its already complete
	XTASSERT(remotePeer.m_bHandshakeComplete == false);

	// Ask the remote machine to send over its systemID and its sync auth level
	NetworkOutMessagePtr identityMsg = remotePeer.m_connection->CreateMessage(m_messageID);
	identityMsg->Write((byte)IdentityInfo);
	identityMsg->Write((byte)m_syncContext->GetAuthorityLevel());
	identityMsg->Write(m_syncContext->GetLocalSystemID());

	identityMsg->Write(m_syncContext->GetLocalUser()->GetName());
	identityMsg->Write(m_syncContext->GetLocalUser()->GetID());

	remotePeer.m_connection->Send(identityMsg);
}
void ProfileManagerImpl::Update()
{
	// If we're connected to the profiling tool...
	if (m_isConnected)
	{
		// Send the accumulated profiling entries to the profiler tool
		NetworkOutMessagePtr msg = m_connection->CreateMessage(MessageID::Profiling);

		EndRange();

		// Record the time it takes to pack up and send the data
		ProfileEntry sendInfoEntry("Send Profiling Data", 0);
		sendInfoEntry.Start();

		// Add the profiling entries to the outgoing packet
		{
			ScopedLock threadMapLock(m_threadStackMutex);

			// Write the number of threads
			int32 numThreads = (int32)m_threadEntries.size();
			msg->Write(numThreads);

			for (auto mapIt = m_threadEntries.begin(); mapIt != m_threadEntries.end(); ++mapIt)
			{
				ThreadInfoPtr threadInfo = mapIt->second;
				ScopedLock entryListLock(threadInfo->m_mutex);

				// Write the threadID
				msg->Write(threadInfo->m_threadID);

				std::vector<ProfileEntry>& entries = threadInfo->m_entries;

				// Write the number of entries in this thread
				uint32 numEntries = (uint32)threadInfo->m_entries.size();
				msg->Write(numEntries);

				// Write each entry
				for (size_t i = 0; i < numEntries; ++i)
				{
					msg->Write(entries[i].GetName());	// Write the name
					msg->Write(entries[i].GetStartTime());
					msg->Write(entries[i].GetDuration());
					msg->Write(entries[i].GetParent());
				}

				// Clear out the list and get ready for the next frame
				threadInfo->m_currentIndex = -1;
			}

			m_threadEntries.clear();
		}

		// Add the log messages to the packet
		{
			ScopedLock lock(m_logMutex);

			// Write the number of log messages
			uint32 numMessages = (uint32)m_logMessages.size();
			msg->Write(numMessages);

			for (uint32 i = 0; i < numMessages; ++i)
			{
				msg->Write((byte)m_logMessages[i].m_severity);
				msg->Write(m_logMessages[i].m_message);
			}

			m_logMessages.clear();
		}


		BeginRange("Profile Frame");

		m_connection->Send(msg, MessagePriority::Low, MessageReliability::ReliableOrdered, MessageChannel::ProfileChannel);

		// Add the time it took to pack up and send the data to the start of the next frame
		sendInfoEntry.End();
		ThreadInfoPtr threadInfo = GetLocalThreadInfo();
		if (threadInfo)
		{
			ScopedLock lock(threadInfo->m_mutex);
			threadInfo->m_entries.push_back(sendInfoEntry);
		}
	}
}
Example #12
0
void SessionServer::OnNewSessionRequest(const NewSessionRequest& request, const NetworkConnectionPtr& connection)
{
	std::string name = request.GetSessionName();

	XSessionImplPtr session;
	std::string failureReason;

	// Cannot create a session with a name that is too short
	if (name.length() < kMinSessionNameLength)
	{
		failureReason = "Session name must have at least " + std::to_string(kMinSessionNameLength) + " letters";
	}

	// Cannot create a session with a name that is too long
	else if (name.length() > kMaxSessionNameLength)
	{
		failureReason = "Session name cannot be more than " + std::to_string(kMaxSessionNameLength) + " letters";
	}
	else
	{
		// Check to make sure that the requested session name is not already taken
		for (size_t i = 0; i < m_sessions.size(); ++i)
		{
			if (m_sessions[i]->GetName() == name)
			{
				failureReason = "A session with that name already exists";
				break;
			}
		}
	}

	if (failureReason.empty())
	{
		session = CreateNewSession(name, request.GetSessionType());
	}
	
	// If the session was successfully created...
	if (session)
	{
		// Report success.
		std::string address = m_socketMgr->GetLocalAddressForRemoteClient(connection->GetSocket());
		uint16 port = session->GetPort();

		NewSessionReply reply(
			session->GetId(), 
			session->GetType(),
			name, 
			address, 
			port);

		NetworkOutMessagePtr response = connection->CreateMessage(MessageID::SessionControl);

		response->Write(reply.ToJSONString());

		connection->Send(response);
	}
	else
	{
		// Report failure
		NewSessionReply reply(failureReason);

		NetworkOutMessagePtr response = connection->CreateMessage(MessageID::SessionControl);

		response->Write(reply.ToJSONString());

		connection->Send(response);
	}
}
void SessionHandshakeLogic::CreateMessageFromDesktop(const NetworkOutMessagePtr& msg) const
{
	// Schema version
	msg->Write(kXToolsSchemaVersion);
}
void XSessionImpl::OnJoinSessionRequest(const JoinSessionRequest& request, const NetworkConnectionPtr& connection)
{
	// Note: this call will remove the remote client from the list of pending connections
	RemoteClientPtr remoteClient = GetPendingClientForConnection(connection);

	if (remoteClient)
	{
		// Fill in the rest of the info about the user
		remoteClient->m_userName = request.GetUserName();
		remoteClient->m_userID = request.GetUserID();
		remoteClient->m_userMuteState = request.GetMuteState();

		// Check to see if this userID is already in use by someone in the session
		bool bDuplicateUserID = false;
		for (size_t clientIndex = 0; clientIndex < m_clients.size(); ++clientIndex)
		{
			if (m_clients[clientIndex]->m_userID == remoteClient->m_userID)
			{
				bDuplicateUserID = true;
				LogError("UserID %i in session join request is a duplicate of a user already in this session.  ", remoteClient->m_userID);
				break;
			}
		}

		// Check to see if the userID is valid
		bool bIsInvalidUserID = false;
		if (remoteClient->m_userID == User::kInvalidUserID)
		{
			LogError("Received invalid userID");
			bIsInvalidUserID = true;
		}

		// If the connecting user is invalid, then send a failure response and shut down the connection
		if (bIsInvalidUserID || bDuplicateUserID)
		{
			// Reply to the user that they have failed to join the session
			{
				JoinSessionReply reply(false);

				NetworkOutMessagePtr msg = connection->CreateMessage(MessageID::SessionControl);
				msg->Write(reply.ToJSONString());
				connection->Send(msg);
			}

			// Disconnect
			connection->Disconnect();
		}
		else
		{
			LogInfo("User %s at address %s joined session %s", remoteClient->m_userName.c_str(), remoteClient->m_primaryConnection->GetRemoteAddress()->GetString().c_str(), GetName().c_str());

			// Add the user to the real list of clients in the session
			m_clients.push_back(remoteClient);

			// Reply to the user that they have now joined the session successfully
			{
				JoinSessionReply reply(true);

				NetworkOutMessagePtr msg = connection->CreateMessage(MessageID::SessionControl);
				msg->Write(reply.ToJSONString());
				connection->Send(msg);
			}

			// Add the remoteClient to the list that can send and receive broadcasts
			m_broadcaster->AddConnection(remoteClient->m_primaryConnection);
			m_broadcaster->AddConnection(remoteClient->m_secondaryConnection);

			// Add the remoteClient to the sendto forwarder
			m_sendToForwarder->AddConnection(remoteClient->m_userID, remoteClient->m_primaryConnection, remoteClient->m_secondaryConnection);

			// Add the remoteClient to the audio packet processor
			m_audioSessionProcessor->AddConnection(remoteClient->m_primaryConnection);
			m_audioSessionProcessor->AddConnection(remoteClient->m_secondaryConnection);

			// Add the connections to the room manager
			m_roomMgr->AddConnection(remoteClient->m_primaryConnection);
			m_roomMgr->AddConnection(remoteClient->m_secondaryConnection);

			// Add the remoteClient to the list that can share the session's sync data
			m_syncMgr->AddConnection(remoteClient->m_primaryConnection);
			m_internalSyncMgr->AddConnection(remoteClient->m_primaryConnection);

			// Notify the session server to tell all the clients that the new user has joined this session
			m_callback->OnUserJoinedSession(m_id, remoteClient->m_userName, remoteClient->m_userID, remoteClient->m_userMuteState);
		}
	}
}