![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
#include <ChatServer.h>
Public Member Functions | |
| ChatServer (void) | |
| ~ChatServer (void) | |
Static Public Member Functions | |
| static void | ClientConnectionThread () |
| static void | ServerConnectionThread () |
Static Private Attributes | |
| static unsigned int | lastUsedClientId = 0 |
| static tbb::concurrent_hash_map < unsigned int, std::vector < int > > | m_mChatGroupMap |
| static tbb::concurrent_hash_map < unsigned int, std::vector < RakString > > | m_mPendingUserMessages |
| static tbb::concurrent_hash_map < unsigned int, std::vector < int > > | m_mUserChatGroupMap |
| static tbb::concurrent_hash_map < SystemAddress, unsigned int, SystemAddressCompare > | m_vChatUserRegister |
| static const int | MAX_NUMBER_OF_CHAT_GROUPS = 2048 |
| static const int | MAX_NUMBER_OF_CHAT_GROUPS_PER_USER = 16 |
| static const int | MAX_NUMBER_OF_USERS_PER_GROUP = 2048 |
Definition at line 50 of file ChatServer.h.
| SraNetwork::ChatServer::ChatServer | ( | void | ) |
Definition at line 17 of file ChatServer.cpp.
{
}
| SraNetwork::ChatServer::~ChatServer | ( | void | ) |
Definition at line 21 of file ChatServer.cpp.
{
}
| void SraNetwork::ChatServer::ClientConnectionThread | ( | ) | [static] |
Definition at line 25 of file ChatServer.cpp.
References SraNetwork::SendMessageToChannelPacket::channelId, SraNetwork::CHAT_CLIENT_PORT, SraNetwork::CLIENT_CHAT_PORT, RakNet::Packet::data, RakNet::RakPeerInterface::DeallocatePacket(), SraNetwork::SendMessageToChannelPacket::Deserialize(), SraNetwork::SraPacket::Deserialize(), SraNetwork::ID_CHAT_CHANNEL_MESSAGE, ID_NEW_INCOMING_CONNECTION, RakNet::Packet::length, m_mChatGroupMap, m_mUserChatGroupMap, SraNetwork::m_rClientInterface, m_vChatUserRegister, MEDIUM_PRIORITY, SraNetwork::SraPacket::opCode, RakNet::RakPeerInterface::Receive(), RELIABLE_ORDERED, RakNet::RakPeerInterface::Send(), RakNet::RakPeerInterface::SetMaximumIncomingConnections(), RakNet::RakPeerInterface::Startup(), stream, and RakNet::Packet::systemAddress.
Referenced by main().
{
printf("Listening for chat clients ..... \n");
RakPeerInterface *m_rClientInterface = RakPeerInterface::GetInstance();
SocketDescriptor chatSocket(SraNetwork::CHAT_CLIENT_PORT, 0);
m_rClientInterface->Startup(2, &chatSocket, 1);
m_rClientInterface->SetMaximumIncomingConnections(2); //2 ?
bool running = true;
while (running)
{
Packet* m_pPacket = m_rClientInterface->Receive();
if (m_pPacket)
{
if (m_pPacket->data[0] == ID_NEW_INCOMING_CONNECTION)
{
printf("Chat client connected\n");
}
else
{
// Now for our own packets.
BitStream stream(m_pPacket->data, m_pPacket->length, false);
SraPacket sraPacket;
sraPacket.Deserialize(&stream);
if (sraPacket.opCode == ID_CHAT_CHANNEL_MESSAGE)
{
SendMessageToChannelPacket chatPacket;
chatPacket.Deserialize(&stream);
printf("Client sent a message to channel %d\n", chatPacket.channelId);
// TODO: Maybe we should move this to a separated class, like
// the world server message pump ...
// First we have to check if the channel exists and if the user is in it.
// We will do this by simply checking the user chat group list:
tbb::concurrent_hash_map<SystemAddress, unsigned int, SystemAddressCompare>::const_accessor acc;
unsigned int clientID = -1;
if (m_vChatUserRegister.find(acc, m_pPacket->systemAddress) )
{
// We already have create an id for this client, so use it
clientID = acc->second;
} else
{
printf("User is not registered, ignoring the message\n");
}
// Whoa this is ugly and will suck a lot of performance....find a better solution!!!
// Search for the channel:
tbb::concurrent_hash_map<unsigned int, std::vector<int>>::const_accessor userGroupsAcc;
// Get user channel list.
if (m_mUserChatGroupMap.find(userGroupsAcc, clientID))
{
// now find the channel id :
bool found = false;
for (std::vector<int>::const_iterator vit = userGroupsAcc->second.begin(); vit != userGroupsAcc->second.end(); ++vit)
{
if ( *vit == chatPacket.channelId)
{
printf("Found channel\n");
found = true;
break;
}
}
if (found)
{
// Ok the user is in this channel, so now send a message to all clients
// that are in this channel:
tbb::concurrent_hash_map<unsigned int, std::vector<int>>::const_accessor chatGroupAcc;
if (m_mChatGroupMap.find(chatGroupAcc, chatPacket.channelId))
{
// iterate through all ids:
for (std::vector<int>::const_iterator userIt = chatGroupAcc->second.begin(); userIt != chatGroupAcc->second.end(); ++userIt)
{
// ok nooow we have to get the corresponding system address from this index:
int userID = *userIt;
for (
tbb::concurrent_hash_map<SystemAddress, unsigned int, SystemAddressCompare>::iterator it = m_vChatUserRegister.begin();
it != m_vChatUserRegister.end(); ++it)
{
if ( it->second == *userIt)
{
printf("Sending the message to a user\n");
SystemAddress addr = it->first;
addr.SetPortA(CLIENT_CHAT_PORT);
uint32_t sent =
m_rClientInterface->Send(&stream, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, addr, false);
printf("I have sent %d bytes", sent);
// Skip the rest of the entries.
break;
}
}
}
}
}
}
}
}
}
m_rClientInterface->DeallocatePacket(m_pPacket);
Sleep(10);
}
}
| void SraNetwork::ChatServer::ServerConnectionThread | ( | ) | [static] |
Definition at line 131 of file ChatServer.cpp.
References SraNetwork::JoinChannelPacket::channelId, SraNetwork::CHAT_SERVER_PORT, SraNetwork::JoinChannelPacket::clientAddress, RakNet::RakPeerInterface::Connect(), RakNet::Packet::data, RakNet::RakPeerInterface::DeallocatePacket(), SraNetwork::JoinChannelPacket::Deserialize(), SraNetwork::SraPacket::Deserialize(), SraNetwork::ID_CHAT_CHANNEL_REGISTER, ID_CONNECTION_ATTEMPT_FAILED, ID_CONNECTION_LOST, ID_CONNECTION_REQUEST_ACCEPTED, lastUsedClientId, RakNet::Packet::length, m_mChatGroupMap, m_mUserChatGroupMap, m_rServerInterface, m_vChatUserRegister, MAX_NUMBER_OF_CHAT_GROUPS, MAX_NUMBER_OF_CHAT_GROUPS_PER_USER, MAX_NUMBER_OF_USERS_PER_GROUP, MEDIUM_PRIORITY, SraNetwork::SraPacket::opCode, RakNet::RakPeerInterface::Receive(), RELIABLE_ORDERED, RakNet::RakPeerInterface::Send(), SraNetwork::JoinChannelPacket::Serialize(), SraNetwork::SERVER_CHAT_PORT, RakNet::RakPeerInterface::Shutdown(), RakNet::RakPeerInterface::Startup(), stream, RakNet::UNASSIGNED_SYSTEM_ADDRESS, and SraNetwork::WORLD_SERVER_ADDR.
Referenced by main().
{
//Connect to world server
RakPeerInterface *m_rServerInterface = RakPeerInterface::GetInstance();
SocketDescriptor chatSocket(SraNetwork::CHAT_SERVER_PORT, 0);
m_rServerInterface->Startup(1, &chatSocket, 1);
m_rServerInterface->Connect(SraNetwork::WORLD_SERVER_ADDR, SraNetwork::SERVER_CHAT_PORT, 0, 0, 0);
printf("Connecting to world server\n");
bool done = false;
bool result = false; //don't return in loop so we can shut down RakNet before exiting
while (!done) //Block while connecing
{
Packet* m_pPacket = m_rServerInterface->Receive();
if (m_pPacket)
{
if (m_pPacket->data[0] == ID_CONNECTION_REQUEST_ACCEPTED)
{
result = true;
}
else if (m_pPacket->data[0] == ID_CONNECTION_ATTEMPT_FAILED)
{
printf("Failed: connection attempt failed\n");
} else
{
printf("Failed: Unknown opcode %d\n", m_pPacket->data[0]);
}
m_rServerInterface->DeallocatePacket(m_pPacket);
m_pPacket = 0;
done = true;
}
Sleep(10);
}
if (!result)
{
printf("Failed to connect to world, exiting now\n");
m_rServerInterface->Shutdown(0);
return;
}
printf("Connection established, waiting for chat connections\n");
bool running = true; //maybe we do not need this, but i don't like while(1) :P
while (running)
{
Packet* m_pPacket = m_rServerInterface->Receive();
if (m_pPacket)
{
if ( m_pPacket->data[0] == ID_CONNECTION_LOST ) {
// Do we really need this hard connection to the world?
// we could also run without it.
printf("Lost connection to world server ! Shutting down now\n");
running = false;
}
else
{
// Now for our own packets.
BitStream stream(m_pPacket->data, m_pPacket->length, false);
SraPacket sraPacket;
sraPacket.Deserialize(&stream);
if (sraPacket.opCode == ID_CHAT_CHANNEL_REGISTER)
{
bool success = true;
JoinChannelPacket joinPacket;
joinPacket.Deserialize(&stream);
printf("Received chat channel registration message for channel %d", joinPacket.channelId);
tbb::concurrent_hash_map<SystemAddress, unsigned int, SystemAddressCompare>::accessor acc;
unsigned int clientID = -1;
if (m_vChatUserRegister.find(acc, joinPacket.clientAddress) )
{
// We already have create an id for this client, so use it
clientID = acc->second;
} else
{
// Well we coooouuuld check if the modded value
// is already in use, but UINT_MAX is 2^32 wich should be
// large enough to be quite sure this should not happen...
lastUsedClientId = (lastUsedClientId+1)%UINT_MAX;
clientID = lastUsedClientId;
m_vChatUserRegister.insert( acc, joinPacket.clientAddress);
acc->second = clientID;
}
printf("User has clientID %d ", clientID);
// Add requested channel to the users list of channels.
tbb::concurrent_hash_map<unsigned int, std::vector<int>>::accessor userGroupsAcc;
if (m_mUserChatGroupMap.find(userGroupsAcc, joinPacket.channelId))
{
// if we already have a list for this user,
// so simply add the new channel.
if (userGroupsAcc->second.size() <= MAX_NUMBER_OF_CHAT_GROUPS_PER_USER)
{
printf("Adding channel to user\n");
userGroupsAcc->second.push_back(joinPacket.channelId);
}
else
{
printf("Error: User exceeded the max number of chat groups!\n");
success = false;
}
}
else
{
printf("Creating a new group list\n");
// if not, we need to create a new user list.
std::vector<int> userList;
userList.push_back(joinPacket.channelId);
m_mUserChatGroupMap.insert(userGroupsAcc, clientID);
userGroupsAcc->second = userList;
}
// Now we need to find the channel list the user wants to join
tbb::concurrent_hash_map<unsigned int, std::vector<int>>::accessor chatGroupsAcc;
if (m_mChatGroupMap.find(chatGroupsAcc, joinPacket.channelId))
{
// if we already the selected channel,
// so simply add the user.
if (chatGroupsAcc->second.size() <= MAX_NUMBER_OF_USERS_PER_GROUP)
{
printf("Adding user to channel\n");
chatGroupsAcc->second.push_back(clientID);
}
else
{
printf("Error: To many users in chat group\n");
success = false;
}
}
else
{
if (m_mChatGroupMap.size() <= MAX_NUMBER_OF_CHAT_GROUPS)
{
printf("Creating new chat group\n");
// if not, we will create a new chat group
std::vector<int> userList;
userList.push_back(clientID);
m_mChatGroupMap.insert(chatGroupsAcc, joinPacket.channelId);
chatGroupsAcc->second = userList;
}
else
{
printf("Error: Max number of chat groups exceeded\n");
success = false;
}
}
// After the joinig process has completed, we will sent a message
// to the user. Be sure to do this always at the end so a potential
// error will not send a return message.
if (success)
{
printf("Send success message to server/client \n");
// Send a message to the player that contains our ip
JoinChannelPacket rp;
// This is used to indicate a success message.
rp.channelId = 0;
rp.clientAddress = joinPacket.clientAddress;
// This is kinda ugly: Because we don't have the socket
// to the client, this message has to be sent back to the server
// and forwarded to the client.
BitStream bs;
rp.Serialize(&bs);
m_rServerInterface->Send(&bs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
}
}
}
}
m_rServerInterface->DeallocatePacket(m_pPacket);
Sleep(10);
}
}
unsigned int SraNetwork::ChatServer::lastUsedClientId = 0 [static, private] |
Definition at line 79 of file ChatServer.h.
Referenced by ServerConnectionThread().
tbb::concurrent_hash_map< unsigned int, std::vector< int > > SraNetwork::ChatServer::m_mChatGroupMap [static, private] |
Definition at line 76 of file ChatServer.h.
Referenced by ClientConnectionThread(), and ServerConnectionThread().
tbb::concurrent_hash_map< unsigned int, std::vector< RakString > > SraNetwork::ChatServer::m_mPendingUserMessages [static, private] |
Definition at line 66 of file ChatServer.h.
tbb::concurrent_hash_map< unsigned int, std::vector< int > > SraNetwork::ChatServer::m_mUserChatGroupMap [static, private] |
Definition at line 72 of file ChatServer.h.
Referenced by ClientConnectionThread(), and ServerConnectionThread().
tbb::concurrent_hash_map< SystemAddress, unsigned int, SystemAddressCompare > SraNetwork::ChatServer::m_vChatUserRegister [static, private] |
Definition at line 62 of file ChatServer.h.
Referenced by ClientConnectionThread(), and ServerConnectionThread().
const int SraNetwork::ChatServer::MAX_NUMBER_OF_CHAT_GROUPS = 2048 [static, private] |
Definition at line 82 of file ChatServer.h.
Referenced by ServerConnectionThread().
const int SraNetwork::ChatServer::MAX_NUMBER_OF_CHAT_GROUPS_PER_USER = 16 [static, private] |
Definition at line 85 of file ChatServer.h.
Referenced by ServerConnectionThread().
const int SraNetwork::ChatServer::MAX_NUMBER_OF_USERS_PER_GROUP = 2048 [static, private] |
Definition at line 88 of file ChatServer.h.
Referenced by ServerConnectionThread().
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.