// TODO: @student : extend the protocol. // so the receiver can split the package into name and content void ClientChatNetPackageDispatcher::dispatchPacket(unsigned char packetIdentifier, NativePacket* nativePacket ) { NetMessageIDTypes eNetMessageID(static_cast<NetMessageIDTypes>(packetIdentifier)); const bool validMessageId((eNetMessageID > NETMSG_ID_START) && (eNetMessageID < NETMSG_ID_END)); if(validMessageId == false) { return; } switch(eNetMessageID) { case NETMSG_ID_CHATLINE: { const char* message = (const char*)nativePacket->data; // skip the packet identifier message++; if(isEmptyString(message) == true) { getPeer()->log(ELogType_Error, "received an empty chat message"); } else { // TODO: @student : split the packet ... ChatMessage chatMessage("---", message); addChatMessage(chatMessage); } } break; case NETMSG_ID_JSONOBJECT: { // TODO: @student : this might not be enough ... const char* message = (const char*)nativePacket->data; // skip the packet identifier message++; if(isEmptyString(message) == true) { getPeer()->log(ELogType_Error, "received an empty chat message"); } else { SLAString json(message); getPeer()->log(ELogType_Info, "received json %s", json.c_str()); CCDictionary* dictionary = CCJSONConverter::dictionaryFrom(json.c_str()); getPeer()->log(ELogType_Info, dictionary); // DONE: @student : read the relevant dictionary members and pass them to the chat message CCObject *aMessage = dictionary->objectForKey("message"); CCDictionary *messDictionary = dynamic_cast<CCDictionary*>(aMessage); const CCString *aSender = messDictionary->valueForKey("sender"); const CCString *aContent = messDictionary->valueForKey("content"); ChatMessage chatMessage(aSender->getCString(), aContent->getCString()); addChatMessage(chatMessage); } } break; default: break; } }
/////////////////////// // Private message void IRCClient::parsePrivmsg(const IRCClient::IRCCommand &cmd) { // Check if (cmd.params.size() < 2 ) return; // Add the message std::string nick = cmd.sender.substr(0, cmd.sender.find('!')); std::string text; std::string my_nick = m_myNick; if (m_nickUniqueNumber >= 0) my_nick += itoa(m_nickUniqueNumber); IRCTextType type = IRC_TEXT_CHAT; if (cmd.params[1].size() && cmd.params[1][0] == '\1' && *cmd.params[1].rbegin() == '\1') { // Action message text = cmd.params[1].substr(1, cmd.params[1].size() - 2); replace(text, "ACTION", nick); type = IRC_TEXT_ACTION; } else if (cmd.params[0] == my_nick) { text = nick + ": " + cmd.params[1]; type = IRC_TEXT_PRIVATE; } else text = nick + ": " + cmd.params[1]; addChatMessage(ircFormattingToHtml( text ), type); }
/////////////////// // Kicked out of the server void IRCClient::parseKicked(const IRCClient::IRCCommand &cmd) { // Get our real nick (add the unique number) for comparison std::string real_nick = m_myNick; if (m_nickUniqueNumber >= 0) real_nick += itoa(m_nickUniqueNumber); // Invalid command if (cmd.params.size() < 2) return; // Check that it was us who gets kicked if (cmd.params[1] != m_myNick) return; // Get the kick reason std::string reason = "No reason was given"; if (cmd.params.size() >= 3) reason = cmd.params[2]; // Inform the user addChatMessage("You have been kicked: " + reason, IRC_TEXT_NOTICE); // Disconnect disconnect(); }
// TODO: @student : extend the protocol. // so the receiver can split the package into name and content void ServerChatNetPackageDispatcher::dispatchPacket(unsigned char packetIdentifier, NativePacket* nativePacket ) { NetMessageIDTypes eNetMessageID(static_cast<NetMessageIDTypes>(packetIdentifier)); const bool validMessageId((eNetMessageID > NETMSG_ID_START) && (eNetMessageID < NETMSG_ID_END)); if(validMessageId == false) { return; } switch(eNetMessageID) { case NETMSG_ID_CHATLINE: { const char* message = (const char*)nativePacket->data; // skip the packet identifier message++; if(isEmptyString(message) == true) { getPeer()->log(ELogType_Error, "received an empty chat message"); } else { // TODO: split the packet ... ChatMessage chatMessage("---", message); addChatMessage(chatMessage); // now broadcast this message to everyone else connected to this peer // except for the sender getPeer()->accessRakNetPeer()->Send((const char*)nativePacket->data, nativePacket->length, HIGH_PRIORITY, RELIABLE_ORDERED, 0, nativePacket->systemAddress, true); } } break; default: break; } }
/////////////////////////// // Fatal error from the server void IRCClient::parseError(const IRCClient::IRCCommand &cmd) { if (cmd.params.size() > 0) { warnings("IRC server error: " + cmd.params[0] + "\n"); addChatMessage("Server error: " + cmd.params[0], IRC_TEXT_NOTICE); disconnect(); } }
void IRCLobby::sendChatMessage(const std::string& user, const std::string& line) { std::string chatline = "#"; chatline += line; addChatMessage(user, line); return sendIRCMessageLine(chatline); }
void IRCLobby::changeNickName(const std::string &nick) { std::stringstream notice; notice << "Changing nickname to: " << nick; addChatMessage("Notice",notice.str()); setNickName(nick); sendNickName(); }
/////////////////////// // Notice void IRCClient::parseNotice(const IRCClient::IRCCommand &cmd) { // Notice is actually a chat message // Check if (cmd.params.size() < 2 ) return; // Ignore any notices before joining the channel (they are more or less some server spam) if (m_authorizedState != AUTH_JOINED_CHANNEL) return; // Get the nick std::string nick = cmd.sender.substr(0, cmd.sender.find('!')); // Add the message std::string text; if (nick.size()) text = nick + ": " + cmd.params[1]; else text = cmd.params[1]; addChatMessage(text, IRC_TEXT_NOTICE); }
void IRCClient::parseTopic(const IRCCommand& cmd) { if( cmd.params.size() < 3 ) return; addChatMessage("Topic: " + cmd.params[2], IRC_TEXT_NOTICE); };
// read a line of irc and process it. void IRCLobby::processMessage() { assert(irc_server_socket != 0); char buf[1024]; char *host, *mess, *host_end, *user_end, *code,*irc_user,*real_user, *buf_start; readIRCLine(buf, sizeof(buf)); #ifndef WITHOUT_NETPANZER LOGGER.debug("recv irc:%s",buf); #endif buf_start=buf; if(buf[0]==':') { buf_start++; } real_user=irc_user=buf_start; if(strncmp(real_user,nickname_prefix,sizeof(nickname_prefix)-1)==0) { real_user+=sizeof(nickname_prefix)-1; } code=irc_user; // skip 1 word and spaces behind it while(*code && !isspace(*code)) { code++; } while(*code && isspace(*code)) { code++; } if((mess=strchr(code,':'))==NULL) { return; } mess++; char *code_end=code; while(*code_end && !isspace(*code_end)) code_end++; *code_end=0; int code_i=atoi(code); if(code_i == 433) { // wrong user name, change the number at the end char newplayer[256]; char *p; strncpy(newplayer,nickname.c_str(),sizeof(newplayer)-2); newplayer[sizeof(newplayer)-2]=0; p=strchr(newplayer,0); if(isdigit(p[-1])) { p--; while(isdigit(*p) && p>newplayer) p--; p++; } snprintf(p,(newplayer+sizeof(newplayer))-p,"%i",atoi(p)+1); changeNickName(newplayer); return; } if(code_i==1) { sendLoginInfo(); return; } if(code_i>=400 && code_i<500) { addChatMessage("Error",mess); LOG(("IRC:%s",buf)); return; } if(strcmp(code,"NOTICE")==0) { addChatMessage("Lobby",mess); return; } if(code_i==353) { char user_list[1024]; char *u=user_list; char *m=mess; while(*m) { if(strncmp(m,nickname_prefix,sizeof(nickname_prefix)-1)==0) { m+=sizeof(nickname_prefix)-1; } *u++=*m++; } *u=0; addChatMessage("Lobby",user_list); return; } if(strcmp(code,"PONG")==0) { expected_ping=0; return; } if(strcmp(code,"PING")==0 || strncmp(buf,"PING",4)==0) { std::stringstream pong; pong << "PONG " <<mess; sendIRCLine(pong.str()); return; } // get remote user/host if( (host=strchr(buf,'@'))==0 || (user_end=strchr(buf,'!'))==0 ) { return; } *host++=0; *user_end++=0; if(strcmp(code,"JOIN")==0) { std::string joined(real_user); joined+=" has arrived in lobby"; addChatMessage("",joined); return; } if(strcmp(code,"PART")==0 || strcmp(code,"QUIT")==0) { std::string leave(real_user); leave+=" has left the lobby"; addChatMessage("",leave); return; } if((host_end=strchr(host,' '))==0) { return; } *host_end++=0; while(isspace(*host_end)) host_end++; if(strcmp(code,"PRIVMSG")!=0) { return; } if(mess[0]=='#') { // this is a chat message addChatMessage(real_user, mess+1); return; } if(mess[0]=='-') { // this is an internal message if(strcmp(mess+1, ask_server_running_mess)==0) { // reply with server details sendServerInfo(irc_user); } else if(strncmp(mess+1,server_running_mess,sizeof(server_running_mess)-1)==0) { // add a server to the list const char *p=mess+strlen(server_running_mess)+1; const char *map; int players=atoi(p); if((p=strchr(p,'/'))==0) { LOG(("bad server description: %s\n",mess)); return; } int max_players=atoi(++p); int port=_NETPANZER_DEFAULT_PORT_TCP; char *port_str; if((port_str=strstr(p,"port:"))!=0) { port=atoi(port_str+5); } if((map=strstr(p,"map:"))==0) { LOG(("no map name: %s\n",mess)); return; } map+=4; GameServer *server = game_servers->find(host, port); if(server==0) { SDL_mutexP(game_servers_mutex); game_servers->push_back( GameServer(host, port, irc_user,real_user,map, players, max_players)); SDL_mutexV(game_servers_mutex); } else { server->irc_user = irc_user; server->real_user = real_user; server->map = map; server->playercount = players; server->max_players = max_players; } } else if(strncmp(mess+1,leaving_mess,sizeof(leaving_mess)-1)==0) { addChatMessage(real_user,mess); } } }