Files
mcpe/thirdparty/raknet/RelayPlugin.cpp
iProgramInCpp 9642818a88 * Initial commit.
:)
2023-07-30 22:22:02 +03:00

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_*