Example #1
0
void messagesLoop()
{
	vector<size_t> messages_ids;
	Message msg;
	Group online;
	string src;
	string dst;
	string net_msg;
	int sock;
	size_t msg_id;

	while(true)
	{
		chat_mtx.lock();	
		messages_ids = chat.getMessagesIds();		
		for(auto const& id: messages_ids)
		{
			online = chat.getGroup(ONLINE_GROUP);
			msg = chat.getMessage(id);
			src = msg.getSrcUserName();
			dst = msg.getDstUserName();
			bool is_file = msg.hasTitle();
			if(online.has(src) && online.has(dst))
			{
				sock = chat.getSocketFromUser(dst);	
				if(is_file)
					net_msg = hostToNetFileIncoming(msg);
				else
					net_msg = hostToNetMsgIncoming(msg);
				//cout << "sock1 = " << sock << endl;
				//sending message to destiny user
				if(send(sock, net_msg) < 0)
				{
					cout << "error sending message from " + src + " to " + dst
						<< ":" << endl;
					perror("");
				}
				else
				{
					msg_id = hash<Message>{}(msg);
					chat.delMessage(msg_id);
					sock = chat.getSocketFromUser(src);	
					//cout << "sock2 = " << sock << endl;
					if(is_file)
						net_msg = hostToNetFileSent(msg_id);
					else
						net_msg = hostToNetMsgSent(msg_id);
					//notificating source user
					if(send(sock, net_msg) < 0)
					{
						cout << "error sending " << (is_file?"file":"message")
							<< " from " << src << " to " << dst << ":" << endl;
						perror("");
					}
				}
			}
		}
		chat_mtx.unlock();	

		this_thread::sleep_for(chrono::milliseconds(MSG_LOOP_TIME_MS));
	}
}
void ChatMsgProcessor::processMsg(MessageInterface* msg)
{
	// Pseudocode:
	// Get common header
	CommonHeader* header = msg->getHeader();
	// Determine sub type for message
	Msg::Sub::Type subtype = header->getMsgSubtype();
	// Retrieve the payload
	Chat* ChatMessage = ((Message<Chat>*)msg)->getPayload();
	// If subtype == normal (1)
	if (Msg::Sub::NORMAL == subtype)
	{
		std::cout << "Processing normal chat Message\n";
		// Get the client info for the client id
		ClientInfo* client = m_MessageProcessor->client_manager->getClientInfo(header->getClientID());
		// try to get chat room infor
		ChatRoomInfo* chatRoom = m_MessageProcessor->chatroom_manager->getChatRoomInfo(header->getDestinationID());
		// if nothing comes back, then it's not a valid chat room
		if (NULL == chatRoom)
		{
			CommonHeader* returnHeader = new CommonHeader(Msg::STATUS_AND_ERROR, Msg::Sub::UNKNOWN, 
				header->getDestinationID(), header->getClientID());
			StatusAndError* status = new StatusAndError(Status::INVALID_DESTINATION_ID, 
				Msg::CHAT, Msg::Sub::NORMAL, "Destination is not a chat room.");
			Message<StatusAndError>* returnMsg = new Message<StatusAndError>(*returnHeader, *status);

			m_ComManager->sendMessage(returnMsg);

			delete returnHeader;
			delete status;
			delete returnMsg;
		}
		// check if user is in chat room
		else if (!chatRoom->CheckChatRoomClients(client->getClientId()))
		{
			CommonHeader* returnHeader = new CommonHeader(Msg::STATUS_AND_ERROR, Msg::Sub::UNKNOWN, 
				header->getDestinationID(), header->getClientID());
			StatusAndError* status = new StatusAndError(Status::INVALID_DESTINATION_ID, 
				Msg::CHAT, Msg::Sub::NORMAL, "User is not in destination chat room.");
			Message<StatusAndError>* returnMsg = new Message<StatusAndError>(*returnHeader, *status);

			m_ComManager->sendMessage(returnMsg);

			delete returnHeader;
			delete status;
			delete returnMsg;
		}
		else
		{
			//first get username of sending client and append to new payload
			ChatMessage->setMessage(m_MessageProcessor->client_manager->
				getClientInfo(header->getClientID())->getUserName()+": "+ChatMessage->getMessage());
			// get list of clients in chat room
			std::vector<int>* clientsInRoom = chatRoom->getClients();
			for (std::vector<int>::const_iterator it = clientsInRoom->begin(); it != clientsInRoom->end(); ++it)
			{
				if(*it == header->getClientID())
				{
					//send echo message with modified payload
					m_ComManager->sendMessage(msg);
				}
				else
				{
					//send message to all other clients in chat room
					CommonHeader* returnHeader = new CommonHeader(Msg::CHAT, Msg::Sub::NORMAL, 
						header->getDestinationID(), *it);
					Message<Chat>* returnMsg = new Message<Chat>(*returnHeader, *ChatMessage);

					m_ComManager->sendMessage(returnMsg,*it);
					delete returnHeader;
					delete returnMsg;
				}
			}
		}
	}
	// else if subtype == whisper (2)
	else if (Msg::Sub::WHISPER == subtype)
	{
		std::cout << "Processing whisper chat Message\n";
		// Get the client info for the client id
		ClientInfo* destClient = m_MessageProcessor->client_manager->getClientInfo(header->getDestinationID());

		// if client is null, they aren't a client or don't exist
		if (NULL == destClient)
		{
			CommonHeader* returnHeader = new CommonHeader(Msg::STATUS_AND_ERROR, Msg::Sub::UNKNOWN, 
				header->getDestinationID(), header->getClientID());
			StatusAndError* status = new StatusAndError(Status::INVALID_DESTINATION_ID, 
				Msg::CHAT, Msg::Sub::WHISPER, "Destination is not a user.");
			Message<StatusAndError>* returnMsg = new Message<StatusAndError>(*returnHeader, *status);

			m_ComManager->sendMessage(returnMsg);

			delete returnHeader;
			delete status;
			delete returnMsg;
		}

		// send message to client 
		CommonHeader* destHeader = new CommonHeader(Msg::CHAT, Msg::Sub::WHISPER, 
			header->getClientID(), header->getDestinationID());
		Chat* destMessage = new Chat(ChatMessage->getMessage());
		Message<Chat>* destReturnMsg = new Message<Chat>(*destHeader, *destMessage);

		m_ComManager->sendMessage(destReturnMsg);

		// send message to sender
		CommonHeader* sourceHeader = new CommonHeader(Msg::CHAT, Msg::Sub::WHISPER, 
			header->getDestinationID(), header->getClientID());
		Chat* sourceMessage = new Chat(ChatMessage->getMessage());
		Message<Chat>* SourceReturnMsg = new Message<Chat>(*sourceHeader, *sourceMessage);

		m_ComManager->sendMessage(SourceReturnMsg);

		delete destHeader;
		delete destMessage;
		delete destReturnMsg;
		delete sourceHeader;
		delete sourceMessage;
		delete SourceReturnMsg;
	}
	// else if subtype == admin (3)
	else if (Msg::Sub::ADMIN == subtype)
	{
		std::cout << "Processing admin chat Message\n";
		// Get the client info for the client id
		ClientInfo* client = m_MessageProcessor->client_manager->getClientInfo(header->getClientID());
		// check if user has permission to send admin message
		if (!client->getAdmin())
		{
			CommonHeader* returnHeader = new CommonHeader(Msg::STATUS_AND_ERROR, Msg::Sub::UNKNOWN, 
				header->getDestinationID(), header->getClientID());
			StatusAndError* status = new StatusAndError(Status::INVALID_DESTINATION_ID, 
				Msg::CHAT, Msg::Sub::ADMIN, "User does not have appropriate permissions.");
			Message<StatusAndError>* returnMsg = new Message<StatusAndError>(*returnHeader, *status);

			m_ComManager->sendMessage(returnMsg);

			delete returnHeader;
			delete status;
			delete returnMsg;
		}
		else
		{
			// get list of all clients
			std::vector<int> clients = m_MessageProcessor->client_manager->getAllClients();
			// send message to each client
			for (std::vector<int>::const_iterator it = clients.begin(); it != clients.end(); ++it)
			{
				CommonHeader* returnHeader = new CommonHeader(Msg::CHAT, Msg::Sub::ADMIN, 
					header->getDestinationID(), ((int)*it));
				Chat* chatmsg = new Chat(ChatMessage->getMessage());
				Message<Chat>* returnMsg = new Message<Chat>(*returnHeader, *chatmsg);
				m_ComManager->sendMessage(returnMsg);
				delete returnHeader;
				delete chatmsg;
				delete returnMsg;
			}
		}
	}
	// Else
	else
	{
		// Send error response
		std::cout << "Invalid Message Subtype received\n";
		CommonHeader* returnHeader = new CommonHeader(Msg::STATUS_AND_ERROR, Msg::Sub::UNKNOWN, 
			header->getDestinationID(), header->getClientID());
		StatusAndError* status = new StatusAndError(Status::INVALID_MESSAGE_SUB_TYPE, 
			Msg::CHAT, header->getMsgSubtype(), "Invalid message subtype");
		Message<StatusAndError>* returnMsg = new Message<StatusAndError>(*returnHeader, *status);
		m_ComManager->sendMessage(returnMsg);
		delete returnHeader;
		delete status;
		delete returnMsg;
	}
}