Ejemplo n.º 1
0
void SendToForwarder::AddConnection(UserID userID, const NetworkConnectionPtr& primaryConnection, const NetworkConnectionPtr& secondaryConnection)
{
	primaryConnection->AddListener(MessageID::SendTo, this);
	secondaryConnection->AddListener(MessageID::SendTo, this);

	ConnectionInfo newConnection;
	newConnection.m_primaryConnection = primaryConnection;
	newConnection.m_secondaryConnection = secondaryConnection;

	m_connections[userID] = newConnection;
}
Ejemplo n.º 2
0
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;
	}
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
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);
	}
}
Ejemplo n.º 6
0
void SyncManagerImpl::AddConnection(const NetworkConnectionPtr& newConnection)
{
#if defined(SYNC_DEBUG)
	LogInfo("%s Adding Connection", m_syncContext->GetLocalUser()->GetName().GetString().c_str());
#endif

	newConnection->AddListener(m_messageID, this);

	m_remoteHosts.resize(m_remoteHosts.size() + 1, RemoteSyncPeer());

	RemoteSyncPeer& newPeer = m_remoteHosts.back();
	newPeer.m_connection = newConnection;

	// Automatically remove this object as a listener when newPeer is destroyed
	newPeer.m_listenerReceipt = CreateRegistrationReceipt(newConnection, &NetworkConnection::RemoveListener, m_messageID, this);

	if (newConnection->IsConnected())
	{
		SendHandshakeMessage(newPeer);
	}
}
Ejemplo n.º 7
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();
	}
}
Ejemplo n.º 8
0
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();
	}
}
Ejemplo n.º 9
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);
	}
}
Ejemplo n.º 10
0
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);
		}
	}
}