Shadowrun: Awakened 29 September 2011 - Build 871
ChatServer.cpp
Go to the documentation of this file.
00001 #include "ChatServer.h"
00002 #include "JoinChannelPacket.h"
00003 #include "ReplyPacket.h"
00004 #include "SendMessageToChannelPacket.h"
00005 
00006 #include <limits.h>
00007 
00008 namespace SraNetwork { 
00009 
00010     unsigned int ChatServer::lastUsedClientId = 0;
00011 
00012     tbb::concurrent_hash_map<SystemAddress, unsigned int, SystemAddressCompare> ChatServer::m_vChatUserRegister;
00013     tbb::concurrent_hash_map<unsigned int, std::vector<RakString>> ChatServer::m_mPendingUserMessages;
00014     tbb::concurrent_hash_map<unsigned int, std::vector<int>> ChatServer::m_mUserChatGroupMap; 
00015     tbb::concurrent_hash_map<unsigned int, std::vector<int>> ChatServer::m_mChatGroupMap; 
00016 
00017     ChatServer::ChatServer(void)
00018     {
00019     }
00020 
00021     ChatServer::~ChatServer(void)
00022     {
00023     }
00024 
00025     void ChatServer::ClientConnectionThread()
00026     {
00027         printf("Listening for chat clients ..... \n");
00028         RakPeerInterface *m_rClientInterface = RakPeerInterface::GetInstance();
00029         SocketDescriptor chatSocket(SraNetwork::CHAT_CLIENT_PORT, 0);
00030         m_rClientInterface->Startup(2, &chatSocket, 1);
00031         m_rClientInterface->SetMaximumIncomingConnections(2); //2 ?
00032 
00033         bool running = true;
00034         while (running)
00035         {
00036             Packet* m_pPacket = m_rClientInterface->Receive();
00037             if (m_pPacket) 
00038             {
00039                 if (m_pPacket->data[0] == ID_NEW_INCOMING_CONNECTION) 
00040                 {
00041                     printf("Chat client connected\n");
00042                 }
00043                 else
00044                 {
00045                     // Now for our own packets. 
00046                     BitStream stream(m_pPacket->data, m_pPacket->length, false);
00047                     SraPacket sraPacket;
00048                     sraPacket.Deserialize(&stream);
00049                     if (sraPacket.opCode == ID_CHAT_CHANNEL_MESSAGE)
00050                     {
00051                         SendMessageToChannelPacket chatPacket;
00052                         chatPacket.Deserialize(&stream);
00053 
00054                         printf("Client sent a message to channel %d\n", chatPacket.channelId);
00055 
00056                         // TODO: Maybe we should move this to a separated class, like
00057                         // the world server message pump ...
00058 
00059                         // First we have to check if the channel exists and if the user is in it.
00060                         // We will do this by simply checking the user chat group list:
00061                         tbb::concurrent_hash_map<SystemAddress, unsigned int, SystemAddressCompare>::const_accessor acc;
00062                         unsigned int clientID = -1;
00063                         if (m_vChatUserRegister.find(acc, m_pPacket->systemAddress) ) 
00064                         {
00065                             // We already have create an id for this client, so use it
00066                             clientID = acc->second;
00067                         } else
00068                         {
00069                             printf("User is not registered, ignoring the message\n");
00070                         }
00071                         
00072                         
00073                         // Whoa this is ugly and will suck a lot of performance....find a better solution!!!
00074 
00075                         // Search for the channel:
00076                         tbb::concurrent_hash_map<unsigned int, std::vector<int>>::const_accessor userGroupsAcc;
00077                         // Get user channel list.
00078                         if (m_mUserChatGroupMap.find(userGroupsAcc, clientID))
00079                         {
00080                             // now find the channel id :
00081                             bool found = false;
00082                             for (std::vector<int>::const_iterator vit = userGroupsAcc->second.begin(); vit != userGroupsAcc->second.end(); ++vit)
00083                             {
00084                                 if ( *vit == chatPacket.channelId)
00085                                 {
00086                                     printf("Found channel\n");
00087                                     found = true;
00088                                     break;
00089                                 }
00090                             }
00091                             if (found)
00092                             {
00093                                 // Ok the user is in this channel, so now send a message to all clients
00094                                 // that are in this channel:
00095                                 tbb::concurrent_hash_map<unsigned int, std::vector<int>>::const_accessor chatGroupAcc;
00096                                 if (m_mChatGroupMap.find(chatGroupAcc, chatPacket.channelId))
00097                                 {
00098                                     // iterate through all ids:
00099                                     for (std::vector<int>::const_iterator userIt = chatGroupAcc->second.begin(); userIt != chatGroupAcc->second.end(); ++userIt)
00100                                     {
00101                                         // ok nooow we have to get the corresponding system address from this index:
00102                                         int userID = *userIt;
00103                                         for (
00104                                             tbb::concurrent_hash_map<SystemAddress, unsigned int, SystemAddressCompare>::iterator it = m_vChatUserRegister.begin(); 
00105                                             it != m_vChatUserRegister.end(); ++it)
00106                                         {
00107                                             if ( it->second == *userIt)
00108                                             {
00109                                                 printf("Sending the message to a user\n");
00110                                                 SystemAddress addr = it->first;
00111                                                 addr.SetPortA(CLIENT_CHAT_PORT);
00112                                                 uint32_t sent = 
00113                                                     m_rClientInterface->Send(&stream, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, addr, false);
00114                                                 printf("I have sent %d bytes", sent);
00115                                                 // Skip the rest of the entries.
00116                                                 break;
00117                                             }
00118                                         }
00119                                     }
00120                                 }
00121                             }
00122                         }
00123                     }
00124                 }
00125             }
00126             m_rClientInterface->DeallocatePacket(m_pPacket);
00127             Sleep(10);
00128         }
00129     }
00130 
00131     void ChatServer::ServerConnectionThread()
00132     {
00133         //Connect to world server
00134         RakPeerInterface *m_rServerInterface = RakPeerInterface::GetInstance();
00135         SocketDescriptor chatSocket(SraNetwork::CHAT_SERVER_PORT, 0);
00136         m_rServerInterface->Startup(1, &chatSocket, 1);
00137         m_rServerInterface->Connect(SraNetwork::WORLD_SERVER_ADDR, SraNetwork::SERVER_CHAT_PORT, 0, 0, 0);
00138 
00139         printf("Connecting to world server\n");
00140 
00141         bool done = false; 
00142         bool result = false; //don't return in loop so we can shut down RakNet before exiting
00143         while (!done) //Block while connecing
00144         {
00145             Packet* m_pPacket = m_rServerInterface->Receive();
00146             if (m_pPacket) 
00147             {
00148                 if (m_pPacket->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) 
00149                 {
00150                     result = true;
00151                 } 
00152                 else if (m_pPacket->data[0] == ID_CONNECTION_ATTEMPT_FAILED)
00153                 {
00154                     printf("Failed: connection attempt failed\n");
00155                 } else 
00156                 {
00157                     printf("Failed: Unknown opcode %d\n", m_pPacket->data[0]);
00158                 }
00159                 m_rServerInterface->DeallocatePacket(m_pPacket);
00160                 m_pPacket = 0;
00161                 done = true;
00162             }
00163             Sleep(10);
00164         }
00165         if (!result)
00166         {
00167             printf("Failed to connect to world, exiting now\n");
00168             m_rServerInterface->Shutdown(0);
00169             return;
00170         }
00171         printf("Connection established, waiting for chat connections\n");
00172 
00173         bool running = true; //maybe we do not need this, but i don't like while(1) :P
00174         while (running)
00175         {
00176             Packet* m_pPacket = m_rServerInterface->Receive();
00177             if (m_pPacket) 
00178             {
00179                 if ( m_pPacket->data[0] == ID_CONNECTION_LOST ) {
00180                     // Do we really need this hard connection to the world?
00181                     // we could also run without it.
00182                     printf("Lost connection to world server ! Shutting down now\n");
00183                     running = false;
00184                 } 
00185                 else
00186                 {
00187                     // Now for our own packets. 
00188                     BitStream stream(m_pPacket->data, m_pPacket->length, false);
00189                     SraPacket sraPacket;
00190                     sraPacket.Deserialize(&stream);
00191                     if (sraPacket.opCode == ID_CHAT_CHANNEL_REGISTER)
00192                     {
00193                         bool success = true;
00194                         JoinChannelPacket joinPacket;
00195                         joinPacket.Deserialize(&stream);
00196 
00197                         printf("Received chat channel registration message for channel %d", joinPacket.channelId);
00198 
00199                         tbb::concurrent_hash_map<SystemAddress, unsigned int, SystemAddressCompare>::accessor acc;
00200                         unsigned int clientID = -1;
00201                         if (m_vChatUserRegister.find(acc, joinPacket.clientAddress) ) 
00202                         {
00203                             // We already have create an id for this client, so use it
00204                             clientID = acc->second;
00205                         } else
00206                         {
00207                             // Well we coooouuuld check if the modded value
00208                             // is already in use, but UINT_MAX is 2^32 wich should be 
00209                             // large enough to be quite sure this should not happen...
00210                             lastUsedClientId = (lastUsedClientId+1)%UINT_MAX;
00211                             clientID = lastUsedClientId;
00212                             m_vChatUserRegister.insert( acc, joinPacket.clientAddress);
00213                             acc->second = clientID;
00214                         }
00215                         printf("User has clientID %d ", clientID);
00216                         // Add requested channel to the users list of channels.
00217                         tbb::concurrent_hash_map<unsigned int, std::vector<int>>::accessor userGroupsAcc;
00218                         if (m_mUserChatGroupMap.find(userGroupsAcc, joinPacket.channelId))
00219                         {
00220                             // if we already have a list for this user, 
00221                             // so simply add the new channel.
00222                             if (userGroupsAcc->second.size() <= MAX_NUMBER_OF_CHAT_GROUPS_PER_USER)
00223                             {
00224                                 printf("Adding channel to user\n");
00225                                 userGroupsAcc->second.push_back(joinPacket.channelId);
00226                             } 
00227                             else 
00228                             {
00229                                 printf("Error: User exceeded the max number of chat groups!\n");
00230                                 success = false;
00231                             }
00232                         } 
00233                         else 
00234                         {
00235                             printf("Creating a new group list\n");
00236                             // if not, we need to create a new user list.
00237                             std::vector<int> userList;
00238                             userList.push_back(joinPacket.channelId);
00239                             m_mUserChatGroupMap.insert(userGroupsAcc, clientID);
00240                             userGroupsAcc->second = userList;
00241                         }
00242 
00243                         // Now we need to find the channel list the user wants to join
00244                         tbb::concurrent_hash_map<unsigned int, std::vector<int>>::accessor chatGroupsAcc;
00245                         if (m_mChatGroupMap.find(chatGroupsAcc, joinPacket.channelId))
00246                         {
00247                             // if we already the selected channel, 
00248                             // so simply add the user.
00249                             if (chatGroupsAcc->second.size() <= MAX_NUMBER_OF_USERS_PER_GROUP)
00250                             {
00251                                 printf("Adding user to channel\n");
00252                                 chatGroupsAcc->second.push_back(clientID);
00253                             }
00254                             else 
00255                             {
00256                                 printf("Error: To many users in chat group\n");
00257                                 success = false;
00258                             }
00259                         } 
00260                         else 
00261                         {
00262                             if (m_mChatGroupMap.size() <= MAX_NUMBER_OF_CHAT_GROUPS)
00263                             {
00264                                 
00265                                 printf("Creating new chat group\n");
00266                                 // if not, we will create a new chat group
00267                                 std::vector<int> userList;
00268                                 userList.push_back(clientID);
00269                                 m_mChatGroupMap.insert(chatGroupsAcc, joinPacket.channelId);
00270                                 chatGroupsAcc->second = userList;
00271                             }
00272                             else 
00273                             {
00274                                 printf("Error: Max number of chat groups exceeded\n");
00275                                 success = false;
00276                             }
00277                         }
00278 
00279                         // After the joinig process has completed, we will sent a message
00280                         // to the user. Be sure to do this always at the end so a potential
00281                         // error will not send a return message.
00282                         if (success)
00283                         {
00284                             printf("Send success message to server/client \n");
00285                             // Send a message to the player that contains our ip 
00286                             JoinChannelPacket rp;
00287                             // This is used to indicate a success message.
00288                             rp.channelId = 0;
00289                             rp.clientAddress = joinPacket.clientAddress;
00290                             // This is kinda ugly: Because we don't have the socket 
00291                             // to the client, this message has to be sent back to the server
00292                             // and forwarded to the client.
00293                             BitStream bs;
00294                             rp.Serialize(&bs);
00295                             m_rServerInterface->Send(&bs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
00296                         }
00297                     }
00298                 }
00299             }
00300             m_rServerInterface->DeallocatePacket(m_pPacket);
00301             Sleep(10);
00302         }
00303     }
00304 }

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net