void SyncManagerImpl::OnIdentityInfoReceived(const NetworkConnectionPtr& connection, NetworkInMessage& msg)
{
	size_t connectionIndex;
	if (GetIndexOfConnection(connection, connectionIndex))
	{
#if defined(SYNC_DEBUG)
		LogInfo("Sync: Received Handshake");
#endif

		RemoteSyncPeer& remotePeer = m_remoteHosts[connectionIndex];
		remotePeer.m_authorityLevel = static_cast<AuthorityLevel>(msg.ReadByte());
		remotePeer.m_systemID = msg.ReadInt32();
		remotePeer.m_userName = msg.ReadStdString();
		remotePeer.m_userID = msg.ReadInt32();


		// Verify that this systemID is not already in use by another machine.  If so, force a disconnection
		// rather than risk data corruption, because GUIDS are based on SystemIDs
		bool duplicateSystemIDFound = (m_syncContext->GetLocalSystemID() == remotePeer.m_systemID);
		if (!duplicateSystemIDFound)
		{
			for (size_t i = 0; i < m_remoteHosts.size(); ++i)
			{
				if (i == connectionIndex) continue;

				if (m_remoteHosts[i].m_systemID == remotePeer.m_systemID)
				{
					duplicateSystemIDFound = true;
					break;
				}
			}
		}
		
		// The sync system will break down if two machines of equal authority level connect.  
		// So verify that they are different levels, or else disconnect
		bool authLevelsMatch = (remotePeer.m_authorityLevel == m_syncContext->GetAuthorityLevel());

		if (duplicateSystemIDFound || authLevelsMatch)
		{	
			// We're registered to receive disconnect callbacks, so we know that SyncManagerImpl::OnDisconnected()
			// will be called as a result of calling this. 
			if (authLevelsMatch)
			{
				LogError("Two machines with equal authority levels have connected: breaking the connection to avoid sync data corruption");
			}
			else
			{
				LogError("Duplicate system ID detected: breaking the connection to avoid sync data corruption");
			}
			XTASSERT(!duplicateSystemIDFound);
			connection->Disconnect();
		}

		// We should not be receiving a handshake message more than once
		XTASSERT(remotePeer.m_bHandshakeComplete == false);

		remotePeer.m_bHandshakeComplete = true;
	}
}
Example #2
0
void SessionServer::OnMessageReceived(const NetworkConnectionPtr& connection, NetworkInMessage& message)
{
    XStringPtr command = message.ReadString();

	JSONMessagePtr jMsg = JSONMessage::CreateFromMessage(command->GetString());

	// Route the incoming message to the appropriate function to handle it
	if (!m_messageRouter.CallHandler(jMsg, connection))
	{
		// We got a bad or unexpected message; break the connection
		connection->Disconnect();
	}
}
void XSessionImpl::OnMessageReceived(const NetworkConnectionPtr& connection, NetworkInMessage& message)
{
	XStringPtr command = message.ReadString();

	JSONMessagePtr jMsg = JSONMessage::CreateFromMessage(command->GetString());

	// Route the incoming message to the appropriate function to handle it
	if (!m_messageRouter.CallHandler(jMsg, connection))
	{
		// There was a problem with the message that was sent.  Boot the connection
		connection->Disconnect();
	}
}
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);
		}
	}
}