mirror of
https://github.com/celisej567/mcpe.git
synced 2025-12-31 17:49:17 +03:00
433 lines
13 KiB
C++
433 lines
13 KiB
C++
/*
|
|
* Copyright (c) 2014, Oculus VR, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
*/
|
|
|
|
#include "NativeFeatureIncludes.h"
|
|
#if _RAKNET_SUPPORT_RelayPlugin==1
|
|
|
|
#include "RelayPlugin.h"
|
|
#include "MessageIdentifiers.h"
|
|
#include "RakPeerInterface.h"
|
|
#include "BitStream.h"
|
|
|
|
using namespace RakNet;
|
|
|
|
STATIC_FACTORY_DEFINITIONS(RelayPlugin,RelayPlugin);
|
|
|
|
RelayPlugin::RelayPlugin()
|
|
{
|
|
acceptAddParticipantRequests=false;
|
|
}
|
|
|
|
RelayPlugin::~RelayPlugin()
|
|
{
|
|
DataStructures::List<StrAndGuidAndRoom*> itemList;
|
|
DataStructures::List<RakString> keyList;
|
|
strToGuidHash.GetAsList(itemList, keyList, _FILE_AND_LINE_);
|
|
guidToStrHash.Clear(_FILE_AND_LINE_);
|
|
for (unsigned int i=0; i < itemList.Size(); i++)
|
|
RakNet::OP_DELETE(itemList[i], _FILE_AND_LINE_);
|
|
for (unsigned int i=0; i < chatRooms.Size(); i++)
|
|
RakNet::OP_DELETE(chatRooms[i], _FILE_AND_LINE_);
|
|
}
|
|
|
|
RelayPluginEnums RelayPlugin::AddParticipantOnServer(const RakString &key, const RakNetGUID &guid)
|
|
{
|
|
ConnectionState cs = rakPeerInterface->GetConnectionState(guid);
|
|
if (cs!=IS_CONNECTED)
|
|
return RPE_ADD_CLIENT_TARGET_NOT_CONNECTED;
|
|
|
|
if (strToGuidHash.HasData(key)==true)
|
|
return RPE_ADD_CLIENT_NAME_ALREADY_IN_USE; // Name already in use
|
|
|
|
// If GUID is already in use, remove existing
|
|
StrAndGuidAndRoom *strAndGuidExisting;
|
|
if (guidToStrHash.Pop(strAndGuidExisting, guid, _FILE_AND_LINE_))
|
|
{
|
|
strToGuidHash.Remove(strAndGuidExisting->str, _FILE_AND_LINE_);
|
|
RakNet::OP_DELETE(strAndGuidExisting, _FILE_AND_LINE_);
|
|
}
|
|
|
|
StrAndGuidAndRoom *strAndGuid = RakNet::OP_NEW<StrAndGuidAndRoom>(_FILE_AND_LINE_);
|
|
strAndGuid->guid=guid;
|
|
strAndGuid->str=key;
|
|
|
|
strToGuidHash.Push(key, strAndGuid, _FILE_AND_LINE_);
|
|
guidToStrHash.Push(guid, strAndGuid, _FILE_AND_LINE_);
|
|
|
|
return RPE_ADD_CLIENT_SUCCESS;
|
|
}
|
|
void RelayPlugin::RemoveParticipantOnServer(const RakNetGUID &guid)
|
|
{
|
|
StrAndGuidAndRoom *strAndGuid;
|
|
if (guidToStrHash.Pop(strAndGuid, guid, _FILE_AND_LINE_))
|
|
{
|
|
LeaveGroup(&strAndGuid);
|
|
strToGuidHash.Remove(strAndGuid->str, _FILE_AND_LINE_);
|
|
RakNet::OP_DELETE(strAndGuid, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
|
|
void RelayPlugin::SetAcceptAddParticipantRequests(bool accept)
|
|
{
|
|
acceptAddParticipantRequests=accept;
|
|
}
|
|
void RelayPlugin::AddParticipantRequestFromClient(const RakString &key, const RakNetGUID &relayPluginServerGuid)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_ADD_CLIENT_REQUEST_FROM_CLIENT);
|
|
bsOut.WriteCompressed(key);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, relayPluginServerGuid, false);
|
|
}
|
|
void RelayPlugin::RemoveParticipantRequestFromClient(const RakNetGUID &relayPluginServerGuid)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_REMOVE_CLIENT_REQUEST_FROM_CLIENT);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, relayPluginServerGuid, false);
|
|
}
|
|
// Send a message to a server running RelayPlugin, to forward a message to the system identified by \a key
|
|
void RelayPlugin::SendToParticipant(const RakNetGUID &relayPluginServerGuid, const RakString &key, BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_MESSAGE_TO_SERVER_FROM_CLIENT);
|
|
bsOut.WriteCasted<unsigned char>(priority);
|
|
bsOut.WriteCasted<unsigned char>(reliability);
|
|
bsOut.Write(orderingChannel);
|
|
bsOut.WriteCompressed(key);
|
|
bsOut.Write(bitStream);
|
|
SendUnified(&bsOut, priority, reliability, orderingChannel, relayPluginServerGuid, false);
|
|
}
|
|
void RelayPlugin::SendGroupMessage(const RakNetGUID &relayPluginServerGuid, BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_GROUP_MESSAGE_FROM_CLIENT);
|
|
bsOut.WriteCasted<unsigned char>(priority);
|
|
bsOut.WriteCasted<unsigned char>(reliability);
|
|
bsOut.Write(orderingChannel);
|
|
bsOut.Write(bitStream);
|
|
SendUnified(&bsOut, priority, reliability, orderingChannel, relayPluginServerGuid, false);
|
|
}
|
|
void RelayPlugin::LeaveGroup(const RakNetGUID &relayPluginServerGuid)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_LEAVE_GROUP_REQUEST_FROM_CLIENT);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, relayPluginServerGuid, false);
|
|
}
|
|
void RelayPlugin::GetGroupList(const RakNetGUID &relayPluginServerGuid)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_GET_GROUP_LIST_REQUEST_FROM_CLIENT);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, relayPluginServerGuid, false);
|
|
}
|
|
PluginReceiveResult RelayPlugin::OnReceive(Packet *packet)
|
|
{
|
|
if (packet->data[0]==ID_RELAY_PLUGIN)
|
|
{
|
|
switch (packet->data[1])
|
|
{
|
|
case RPE_MESSAGE_TO_SERVER_FROM_CLIENT:
|
|
{
|
|
BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID)*2);
|
|
PacketPriority priority;
|
|
PacketReliability reliability;
|
|
char orderingChannel;
|
|
unsigned char cIn;
|
|
bsIn.Read(cIn);
|
|
priority = (PacketPriority) cIn;
|
|
bsIn.Read(cIn);
|
|
reliability = (PacketReliability) cIn;
|
|
bsIn.Read(orderingChannel);
|
|
RakString key;
|
|
bsIn.ReadCompressed(key);
|
|
BitStream bsData;
|
|
bsIn.Read(&bsData);
|
|
StrAndGuidAndRoom **strAndGuid = strToGuidHash.Peek(key);
|
|
StrAndGuidAndRoom **strAndGuidSender = guidToStrHash.Peek(packet->guid);
|
|
if (strAndGuid && strAndGuidSender)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_MESSAGE_TO_CLIENT_FROM_SERVER);
|
|
bsOut.WriteCompressed( (*strAndGuidSender)->str );
|
|
bsOut.AlignWriteToByteBoundary();
|
|
bsOut.Write(bsData);
|
|
SendUnified(&bsOut, priority, reliability, orderingChannel, (*strAndGuid)->guid, false);
|
|
}
|
|
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
|
|
case RPE_ADD_CLIENT_REQUEST_FROM_CLIENT:
|
|
{
|
|
BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID)*2);
|
|
RakString key;
|
|
bsIn.ReadCompressed(key);
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
if (acceptAddParticipantRequests)
|
|
bsOut.WriteCasted<MessageID>(AddParticipantOnServer(key, packet->guid));
|
|
else
|
|
bsOut.WriteCasted<MessageID>(RPE_ADD_CLIENT_NOT_ALLOWED);
|
|
bsOut.WriteCompressed(key);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
|
|
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
case RPE_REMOVE_CLIENT_REQUEST_FROM_CLIENT:
|
|
{
|
|
RemoveParticipantOnServer(packet->guid);
|
|
}
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case RPE_GROUP_MESSAGE_FROM_CLIENT:
|
|
{
|
|
OnGroupMessageFromClient(packet);
|
|
}
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case RPE_JOIN_GROUP_REQUEST_FROM_CLIENT:
|
|
{
|
|
OnJoinGroupRequestFromClient(packet);
|
|
}
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case RPE_LEAVE_GROUP_REQUEST_FROM_CLIENT:
|
|
{
|
|
OnLeaveGroupRequestFromClient(packet);
|
|
}
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case RPE_GET_GROUP_LIST_REQUEST_FROM_CLIENT:
|
|
{
|
|
SendChatRoomsList(packet->guid);
|
|
}
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
|
|
}
|
|
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
|
|
void RelayPlugin::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
|
|
{
|
|
(void) lostConnectionReason;
|
|
(void) systemAddress;
|
|
|
|
RemoveParticipantOnServer(rakNetGUID);
|
|
}
|
|
|
|
RelayPlugin::RP_Group* RelayPlugin::JoinGroup(RP_Group* room, StrAndGuidAndRoom **strAndGuidSender)
|
|
{
|
|
if (strAndGuidSender==0)
|
|
return 0;
|
|
|
|
NotifyUsersInRoom(room, RPE_USER_ENTERED_ROOM, (*strAndGuidSender)->str);
|
|
StrAndGuid sag;
|
|
sag.guid=(*strAndGuidSender)->guid;
|
|
sag.str=(*strAndGuidSender)->str;
|
|
|
|
room->usersInRoom.Push(sag, _FILE_AND_LINE_);
|
|
(*strAndGuidSender)->currentRoom=room->roomName;
|
|
|
|
return room;
|
|
}
|
|
void RelayPlugin::JoinGroupRequest(const RakNetGUID &relayPluginServerGuid, RakString groupName)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_JOIN_GROUP_REQUEST_FROM_CLIENT);
|
|
bsOut.WriteCompressed(groupName);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, relayPluginServerGuid, false);
|
|
}
|
|
RelayPlugin::RP_Group* RelayPlugin::JoinGroup(RakNetGUID userGuid, RakString roomName)
|
|
{
|
|
StrAndGuidAndRoom **strAndGuidSender = guidToStrHash.Peek(userGuid);
|
|
if (strAndGuidSender)
|
|
{
|
|
if (roomName.IsEmpty())
|
|
return 0;
|
|
|
|
if ((*strAndGuidSender)->currentRoom==roomName)
|
|
return 0;
|
|
|
|
if ((*strAndGuidSender)->currentRoom.IsEmpty()==false)
|
|
LeaveGroup(strAndGuidSender);
|
|
|
|
RakString userName = (*strAndGuidSender)->str;
|
|
|
|
for (unsigned int i=0; i < chatRooms.Size(); i++)
|
|
{
|
|
if (chatRooms[i]->roomName==roomName)
|
|
{
|
|
// Join existing room
|
|
return JoinGroup(chatRooms[i],strAndGuidSender);
|
|
}
|
|
}
|
|
|
|
// Create new room
|
|
RP_Group *room = RakNet::OP_NEW<RP_Group>(_FILE_AND_LINE_);
|
|
room->roomName=roomName;
|
|
chatRooms.Push(room, _FILE_AND_LINE_);
|
|
return JoinGroup(room,strAndGuidSender);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
void RelayPlugin::LeaveGroup(StrAndGuidAndRoom **strAndGuidSender)
|
|
{
|
|
if (strAndGuidSender==0)
|
|
return;
|
|
|
|
RakString userName = (*strAndGuidSender)->str;
|
|
for (unsigned int i=0; i < chatRooms.Size(); i++)
|
|
{
|
|
if (chatRooms[i]->roomName==(*strAndGuidSender)->currentRoom)
|
|
{
|
|
(*strAndGuidSender)->currentRoom.Clear();
|
|
|
|
RP_Group *room = chatRooms[i];
|
|
for (unsigned int j=0; j < room->usersInRoom.Size(); j++)
|
|
{
|
|
if (room->usersInRoom[j].guid==(*strAndGuidSender)->guid)
|
|
{
|
|
room->usersInRoom.RemoveAtIndexFast(j);
|
|
|
|
if (room->usersInRoom.Size()==0)
|
|
{
|
|
RakNet::OP_DELETE(room, _FILE_AND_LINE_);
|
|
chatRooms.RemoveAtIndexFast(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
NotifyUsersInRoom(room, RPE_USER_LEFT_ROOM, userName);
|
|
|
|
return;
|
|
|
|
}
|
|
}
|
|
}
|
|
void RelayPlugin::NotifyUsersInRoom(RP_Group *room, int msg, const RakString& message)
|
|
{
|
|
for (unsigned int i=0; i < room->usersInRoom.Size(); i++)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(msg);
|
|
bsOut.WriteCompressed(message);
|
|
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, room->usersInRoom[i].guid, false);
|
|
}
|
|
}
|
|
void RelayPlugin::SendMessageToRoom(StrAndGuidAndRoom **strAndGuidSender, BitStream* message)
|
|
{
|
|
if ((*strAndGuidSender)->currentRoom.IsEmpty())
|
|
return;
|
|
|
|
for (unsigned int i=0; i < chatRooms.Size(); i++)
|
|
{
|
|
if (chatRooms[i]->roomName==(*strAndGuidSender)->currentRoom)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_GROUP_MSG_FROM_SERVER);
|
|
message->ResetReadPointer();
|
|
bsOut.WriteCompressed((*strAndGuidSender)->str);
|
|
bsOut.AlignWriteToByteBoundary();
|
|
bsOut.Write(message);
|
|
|
|
RP_Group *room = chatRooms[i];
|
|
for (unsigned int i=0; i < room->usersInRoom.Size(); i++)
|
|
{
|
|
if (room->usersInRoom[i].guid!=(*strAndGuidSender)->guid)
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, room->usersInRoom[i].guid, false);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
void RelayPlugin::SendChatRoomsList(RakNetGUID target)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
bsOut.WriteCasted<MessageID>(RPE_GET_GROUP_LIST_REPLY_FROM_SERVER);
|
|
bsOut.WriteCasted<uint16_t>(chatRooms.Size());
|
|
for (unsigned int i=0; i < chatRooms.Size(); i++)
|
|
{
|
|
bsOut.WriteCompressed(chatRooms[i]->roomName);
|
|
bsOut.WriteCasted<uint16_t>(chatRooms[i]->usersInRoom.Size());
|
|
}
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, target, false);
|
|
}
|
|
void RelayPlugin::OnGroupMessageFromClient(Packet *packet)
|
|
{
|
|
BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID)*2);
|
|
|
|
PacketPriority priority;
|
|
PacketReliability reliability;
|
|
char orderingChannel;
|
|
unsigned char cIn;
|
|
bsIn.Read(cIn);
|
|
priority = (PacketPriority) cIn;
|
|
bsIn.Read(cIn);
|
|
reliability = (PacketReliability) cIn;
|
|
bsIn.Read(orderingChannel);
|
|
BitStream bsData;
|
|
bsIn.Read(&bsData);
|
|
|
|
StrAndGuidAndRoom **strAndGuidSender = guidToStrHash.Peek(packet->guid);
|
|
if (strAndGuidSender)
|
|
{
|
|
SendMessageToRoom(strAndGuidSender,&bsData);
|
|
}
|
|
}
|
|
void RelayPlugin::OnJoinGroupRequestFromClient(Packet *packet)
|
|
{
|
|
BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID)*2);
|
|
RakString groupName;
|
|
bsIn.ReadCompressed(groupName);
|
|
RelayPlugin::RP_Group *groupJoined = JoinGroup(packet->guid, groupName);
|
|
|
|
BitStream bsOut;
|
|
bsOut.WriteCasted<MessageID>(ID_RELAY_PLUGIN);
|
|
if (groupJoined)
|
|
{
|
|
bsOut.WriteCasted<MessageID>(RPE_JOIN_GROUP_SUCCESS);
|
|
bsOut.WriteCasted<uint16_t>(groupJoined->usersInRoom.Size());
|
|
for (unsigned int i=0; i < groupJoined->usersInRoom.Size(); i++)
|
|
{
|
|
bsOut.WriteCompressed(groupJoined->usersInRoom[i].str);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bsOut.WriteCasted<MessageID>(RPE_JOIN_GROUP_FAILURE);
|
|
}
|
|
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
|
|
}
|
|
void RelayPlugin::OnLeaveGroupRequestFromClient(Packet *packet)
|
|
{
|
|
BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID)*2);
|
|
StrAndGuidAndRoom **strAndGuidSender = guidToStrHash.Peek(packet->guid);
|
|
if (strAndGuidSender)
|
|
LeaveGroup(strAndGuidSender);
|
|
}
|
|
#endif // _RAKNET_SUPPORT_*
|