/* * This file is a part of VyQChat. * * Copyright (C) 2002-2004 Pawel Stolowski * * VyQChat is free software; you can redestribute it and/or modify it * under terms of GNU General Public License by Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY. See GPL for more details. */ #include "vcprotocol.h" #include "packetdata.h" #include "uuid.h" #include #include #include #include #include #include #include #include #include // // this macro should be used with PacketData operator<< #define PROTOVERSION VY_PROTOMINOR << 0 << VY_PROTOMAJOR << 0 #define VC_PLATFORM "Linux" #define VC_SOFTWARE "VyQChat" #define VY_WHOHERE '0' #define VY_IMHERE '1' #define VY_SAY '2' #define VY_NICKCHANGE '3' #define VY_JOIN '4' #define VY_LEAVE '5' #define VY_MESSAGE '6' #define VY_MASSMESSAGE 'E' #define VY_MESSAGEACK '7' #define VY_REMOTEEXEC '8' #define VY_EXECACK '9' #define VY_ME 'A' #define VY_NEWTOPIC 'B' #define VY_CURRTOPIC 'C' #define VY_CHANGESTAT 'D' #define VY_INFOREQ 'F' #define VY_INFOREQACK 'G' #define VY_BEEP 'H' #define VY_BEEP_SIGNAL '0' #define VY_BEEP_ACK '1' #define VY_SOUNDREQ 'I' #define VY_PRIVATE 'J' #define VY_PRIVATE_JOIN '0' #define VY_PRIVATE_LEAVE '1' #define VY_PRIVATE_SAY '2' #define VY_PRIVATE_ME '3' #define VY_HEREREQ 'L' #define VY_HEREACK 'K' #define VY_CHANGEACTIV 'M' #define VY_REQCHANNELS 'N' #define VY_REQCHANNELSACK 'O' #define VY_PING 'P' #define VY_PINGREQ '0' #define VY_PINGACK '1' #define VY_FLOODNOTIFY 'Z' VCProtocol::VCProtocol(QTextCodec *c, const UUID &uuid, bool useutf): ansicodec(c), wnotifier(NULL), rnotifier(NULL) /*{{{*/ { this->uuid = uuid; utfcodec = QTextCodec::codecForName("UTF-8"); setUseUTF(useutf); srandom(time(NULL)); }/*}}}*/ VCProtocol::~VCProtocol()/*{{{*/ { closeSockets(); }/*}}}*/ void VCProtocol::setAnsiCodec(QTextCodec *c)/*{{{*/ { ansicodec = c; }/*}}}*/ void VCProtocol::setUseUTF(bool f)/*{{{*/ { sndcodec = ((useutf = f)) ? utfcodec : ansicodec; }/*}}}*/ bool VCProtocol::setupBroadcastSockets(const QHostAddress &ip, const QHostAddress &broadcast, unsigned int port)/*{{{*/ { sockaddr_in saddr; int flags; int opt = 1; /*if ((sendsd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket()"); return false; }*/ if ((recvsd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket()"); return false; } if ((setsockopt(recvsd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int)) < 0) || (setsockopt(recvsd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0)) { perror("setsockopt()"); return false; } //setsockopt(recvsd, SOL_SOCKET, SO_NO_CHECK, &opt, sizeof(int)); // // set sockets non-blocking /*if ((flags = fcntl(sendsd, F_GETFL, 0)) < 0) { perror("fcntl()"); return false; } flags |= O_NONBLOCK; if (fcntl(sendsd, F_SETFL, flags) < 0) return false;*/ if ((flags = fcntl(recvsd, F_GETFL, 0)) < 0) return false; flags |= O_NONBLOCK; if (fcntl(recvsd, F_SETFL, flags) < 0) return false; // // bind receiving socket bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); //htonl(ip.toIPv4Address()); saddr.sin_port = htons(port); if (bind(recvsd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { std::cout << ip.toString() << std::endl; perror("1 bind()"); return false; } this->broadcast = broadcast; this->port = port; rnotifier = new QSocketNotifier(recvsd, QSocketNotifier::Read, this); connect(rnotifier, SIGNAL(activated(int)), this, SLOT(dataReceived())); return true; }/*}}}*/ bool VCProtocol::setupMulticastSockets(const QHostAddress &ip, const QHostAddress &multicastgroup, unsigned char ttl, unsigned int port)/*{{{*/ { struct sockaddr_in saddr; int flags; int opt = 1; struct ip_mreq mcast; /*if ((sendsd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket()"); return false; }*/ if ((recvsd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket()"); return false; } if (/*(setsockopt(sendsd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int)) < 0) ||*/ (setsockopt(recvsd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl))<0) || (setsockopt(recvsd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0)) { perror("setsockopt()"); return false; } //setsockopt(recvsd, SOL_SOCKET, SO_NO_CHECK, &opt, sizeof(int)); // // set multicast group mcast.imr_multiaddr.s_addr = htonl(multicastgroup.toIPv4Address()); mcast.imr_interface.s_addr = htonl(ip.toIPv4Address()); if (setsockopt(recvsd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast)) < 0) { perror("can't set multicast group"); return false; } // // set sockets non-blocking /*if ((flags = fcntl(sendsd, F_GETFL, 0)) < 0) { perror("fcntl()"); return false; } flags |= O_NONBLOCK; if (fcntl(sendsd, F_SETFL, flags) < 0) return false;*/ if ((flags = fcntl(recvsd, F_GETFL, 0)) < 0) return false; flags |= O_NONBLOCK; if (fcntl(recvsd, F_SETFL, flags) < 0) return false; // // bind receiving socket bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); //htonl(add.toIPv4Address()); saddr.sin_port = htons(port); if (bind(recvsd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { std::cout << ip.toString() << std::endl; perror("1 bind()"); return false; } this->broadcast = multicastgroup; this->port = port; rnotifier = new QSocketNotifier(recvsd, QSocketNotifier::Read, this); connect(rnotifier, SIGNAL(activated(int)), this, SLOT(dataReceived())); return true; }/*}}}*/ void VCProtocol::closeSockets()/*{{{*/ { //close(sendsd); close(recvsd); if (rnotifier) delete rnotifier; if (wnotifier) delete wnotifier; }/*}}}*/ void VCProtocol::dataReceived()/*{{{*/ { QHostAddress source; sockaddr_in saddr; socklen_t slen = sizeof(struct sockaddr_in); char buffer[VY_MAXPACKETSIZE]; int len = recvfrom(recvsd, buffer, VY_MAXPACKETSIZE, 0, (struct sockaddr *)&saddr, &slen); source.setAddress(ntohl(saddr.sin_addr.s_addr)); std::cout << source.toString() << std::endl; decode(buffer, len, source); }/*}}}*/ QTextCodec *VCProtocol::setUserCodecUTF(const QHostAddress &addr, char f)/*{{{*/ { return setUserCodecUTF(addr, f == '1'); }/*}}}*/ QTextCodec *VCProtocol::setUserCodecUTF(const QHostAddress &addr, bool f)/*{{{*/ { return (usercodec[addr.toIPv4Address()] = f) ? utfcodec : ansicodec; }/*}}}*/ QTextCodec *VCProtocol::codecForUser(const QHostAddress &addr)/*{{{*/ { const Q_INT32 a = addr.toIPv4Address(); if (!usercodec.contains(a)) return ansicodec; return (usercodec[a]) ? utfcodec : ansicodec; }/*}}}*/ bool VCProtocol::get(QCString *str, char *buffer, int &pos, const int p_len)/*{{{*/ { const int spos = pos; for (;postoUnicode(reinterpret_cast(buffer + spos)); ++pos; return true; } } return false; }/*}}}*/ bool VCProtocol::get(char *c, char *buffer, int &pos, const int p_len)/*{{{*/ { if (pos < p_len) { *c = buffer[pos++]; return true; } return false; }/*}}}*/ bool VCProtocol::get(UUID *uuid, char *buffer, int &pos, const int p_len)/*{{{*/ { pos += UUID_LEN; if (pos < p_len) { uuid->set(buffer); return true; } return false; }/*}}}*/ bool VCProtocol::get(Q_INT16 *s, char *buffer, int &pos, const int p_len)/*{{{*/ { if ((pos + sizeof(Q_INT16)) < p_len) { *s = buffer[pos++]<<8; *s |= buffer[pos++]; return true; } return false; }/*}}}*/ bool VCProtocol::get(Q_INT32 *s, char *buffer, int &pos, const int p_len)/*{{{*/ { if ((pos + sizeof(Q_INT32)) < p_len) { *s = buffer[pos++]<<24; *s |= buffer[pos++]<<16; *s |= buffer[pos++]<<8; *s |= buffer[pos++]; return true; } return false; }/*}}}*/ bool VCProtocol::decode(char *p_data, int p_len, const QHostAddress &source)/*{{{*/ { if (*p_data != 'X') //check if it is vypress chat packet return false; const char *p_id = p_data; //packet signature start p_data += 10; //skip packet id char b = *(p_data++); std::cout << b << std::endl; QString from, to, channel, text, host, computer, ip, name, channels, software, time; char status, gender, codepage, ractive, c; UUID uuid; Q_INT32 version, color; int pos = 0; QTextCodec *codec = codecForUser(source); switch (b) { /* WHO HERE * updater */ case VY_WHOHERE: if (!get(&from, p_data, pos, p_len, codec)) return false; emit sig_vc_whohere(source, from); break; /* IM HERE * updater :: responder :: status + remote active :: (version + gender + uuid :: 0000 + cp + color)*/ case VY_IMHERE: get(&to, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); get(&status, p_data, pos, p_len); if (!get(&ractive, p_data, pos, p_len)) return false; get(&c, p_data, pos, p_len); //zero byte if (get(&version, p_data, pos, p_len)) //vc 1.9.x { Q_INT16 tmp; get(&gender, p_data, pos, p_len); get(&uuid, p_data, pos, p_len); get(&c, p_data, pos, p_len); //zero byte get(&tmp, p_data, pos, p_len); //reserverd dword get(&tmp, p_data, pos, p_len); //... get(&codepage, p_data, pos, p_len); get(&color, p_data, pos, p_len); setUserCodecUTF(source, codepage); emit sig_vc_imhere(source, to, from, status, ractive, gender, color); } else emit sig_vc_imhere(source, to, from, status, ractive); break; /* SIMPLE CHAT * channel :: author :: text */ case VY_SAY: get(&channel, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); if (get(&text, p_data, pos, p_len, codec)) emit sig_vc_say(channel, from, text); break; /* ME * channel :: author :: text */ case VY_ME: get(&channel, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); if (!get(&text, p_data, pos, p_len, codec)) return false; emit sig_vc_me(channel, from, text); break; /* NICK CHANGE * old :: new :: gender */ case VY_NICKCHANGE: get(&from, p_data, pos, p_len, codec); get(&to, p_data, pos, p_len, codec); if (!get(&c, p_data, pos, p_len)) return false; emit sig_vc_nickchange(from, to , gender); break; /* BEEP */ case VY_BEEP: b = *(p_data++); switch (b) { /* BEEP SIGNAL * to :: from */ case VY_BEEP_SIGNAL: get(&to, p_data, pos, p_len, codec); if (!get(&from, p_data, pos, p_len, codec)) return false; emit sig_vc_beep(source, to, from); break; /* BEEP ACK * to :: from :: gender */ case VY_BEEP_ACK: get(&to, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); if (!get(&gender, p_data, pos, p_len)) return false; emit sig_vc_beepack(to, from, gender); break; default: break; } break; /* JOIN * who :: channel :: status + gender */ case VY_JOIN: { QCString a_from, a_channel; //raw ansi strings, we don't know codec yet get(&a_from, p_data, pos, p_len); get(&a_channel, p_data, pos, p_len); get(&status, p_data, pos, p_len); if (!get(&gender, p_data, pos, p_len)) return false; if (get(&c, p_data, pos, p_len)) //succeeds for vypresschat >= 1.9.x { if (channel == MAIN_CHANNEL) { get(&version, p_data, pos, p_len); get(&uuid, p_data, pos, p_len); get(&codepage, p_data, pos, p_len); if (!get(&color, p_data, pos, p_len)) return false; } else { if (!get(&codepage, p_data, pos, p_len)) return false; } codec = setUserCodecUTF(source, codepage); } emit sig_vc_join(source, codec->toUnicode(a_from), codec->toUnicode(a_channel), status, gender); break; } /* LEAVE * who :: channel :: gender */ case VY_LEAVE: get(&from, p_data, pos, p_len, codec); get(&channel, p_data, pos, p_len, codec); if (!get(&gender, p_data, pos, p_len)) return false; emit sig_vc_leave(from, channel, gender); break; /* PRIVATE */ case VY_PRIVATE: b = *(p_data++); get(&from, p_data, pos, p_len, codec); get(&to, p_data, pos, p_len, codec); switch (b) { /* PRIVATE JOIN, PRIVATE_LEAVE * from :: to :: gender */ case VY_PRIVATE_JOIN: if (!get(&gender, p_data, pos, p_len)) return false; emit sig_vc_private_join(from, to, gender); break; case VY_PRIVATE_LEAVE: if (!get(&gender, p_data, pos, p_len)) return false; emit sig_vc_private_leave(from, to, gender); break; /* PRIVATE_SAY * from :: to :: text */ case VY_PRIVATE_SAY: if (!get(&text, p_data, pos, p_len, codec)) return false; emit sig_vc_private_say(from, to, text); break; /* PRIVATE ME * from :: to :: text */ case VY_PRIVATE_ME: if (!get(&text, p_data, pos, p_len, codec)) return false; emit sig_vc_private_me(from, to, text); break; default: break; } break; /* MESSAGE * from :: to :: text */ case VY_MESSAGE: { QCString sig; get(&from, p_data, pos, p_len, codec); get(&to, p_data, pos, p_len, codec); if (!get(&text, p_data, pos, p_len, codec)) return false; sig.duplicate(p_id, 10); emit sig_vc_message(source, sig, from, to, text); break; } /* MESSAGEACK * status + whorec :: towhoack :: gender + currentaa :: (sig)*/ case VY_MESSAGEACK: { QCString sig; get(&status, p_data, pos, p_len); get(&from, p_data, pos, p_len, codec); get(&to, p_data, pos, p_len, codec); get(&gender, p_data, pos, p_len); get(&text, p_data, pos, p_len, codec); if (get(&sig, p_data, pos, p_len)) emit sig_vc_messageack(status, from, to, gender, text); else emit sig_vc_messageack(sig, status, from, to, gender, text); break; } /* MASSMESSAGE * from :: to :: text */ case VY_MASSMESSAGE: { QCString sig; get(&from, p_data, pos, p_len, codec); get(&to, p_data, pos, p_len, codec); if (!get(&text, p_data, pos, p_len, codec)) return false; sig.duplicate(p_id, 10); emit sig_vc_massmessage(source, sig, from, to, text); break; } /* HERE REQUEST * from :: channel */ case VY_HEREREQ: get(&from, p_data, pos, p_len, codec); if (!get(&channel, p_data, pos, p_len, codec)) return false; emit sig_vc_herereq(source, from, channel); break; /* HERE ACK * to :: channel :: from :: remote active */ case VY_HEREACK: get(&to, p_data, pos, p_len, codec); get(&channel, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); if (!get(&ractive, p_data, pos, p_len)) return false; emit sig_vc_hereack(to, channel, from, ractive); break; /* PING / PONG * to :: from :: time */ case VY_PING: b = *(p_data++); get(&to, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); get(&time, p_data, pos, p_len, codec); if (b == VY_PINGREQ) emit sig_vc_ping(source, to, from, time); else if (b == VY_PINGACK) emit sig_vc_pong(to, from, time); break; /* INFO REQUEST * to :: from */ case VY_INFOREQ: get(&to, p_data, pos, p_len, codec); if (!get(&from, p_data, pos, p_len, codec)) return false; emit sig_vc_inforeq(to, from); break; /* INFO REQUEST ACK * to :: from :: host :: name :: ip :: channels :: answer :: (platform :: soft )*/ case VY_INFOREQACK: get(&to, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); get(&host, p_data, pos, p_len, codec); get(&name, p_data, pos, p_len, codec); get(&ip, p_data, pos, p_len, codec); get(&channels, p_data, pos, p_len, codec); if (!get(&text, p_data, pos, p_len, codec)) return false; // for vypress chat >= 1.9.x get(&computer, p_data, pos, p_len, codec); get(&software, p_data, pos, p_len, codec); emit sig_vc_inforeqack(source, to, from, host, name, ip, channels, text, computer, software, codecForUser(source) == utfcodec); break; /* CURRENT TOPIC * towho :: channel :: topic */ case VY_CURRTOPIC: get(&to, p_data, pos, p_len, codec); get(&channel, p_data, pos, p_len, codec); if (!get(&text, p_data, pos, p_len, codec)) return false; emit sig_vc_currenttopic(to, channel, text); break; /* NEW TOPIC * channel :: topic */ case VY_NEWTOPIC: get(&channel, p_data, pos, p_len, codec); if (!get(&text, p_data, pos, p_len, codec)) return false; emit sig_vc_newtopic(channel, text); break; /* CHANGE STATUS * who :: status + gender + aa */ case VY_CHANGESTAT: get(&from, p_data, pos, p_len, codec); get(&status, p_data, pos, p_len); get(&gender, p_data, pos, p_len); if (!get(&text, p_data, pos, p_len, codec)) return false; emit sig_vc_changestatus(from, status, gender, text); break; /* FLOOD NOTIFY * to :: from :: seconds */ case VY_FLOODNOTIFY: get(&to, p_data, pos, p_len, codec); get(&from, p_data, pos, p_len, codec); if (!get(&text, p_data, pos, p_len, codec)) return false; emit sig_vc_floodnotify(to, from, text); default: break; } return true; }/*}}}*/ void VCProtocol::send(const QHostAddress &addr, PacketData *packet)/*{{{*/ { if (packet->isOk()) { sockaddr_in saddr; bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(addr.toIPv4Address()); saddr.sin_port = htons(port); int s = sendto(recvsd, packet->dataPtr(), packet->dataLength(), 0, (sockaddr *)&saddr, sizeof(saddr)); if (s<0) perror("send(): "); //else // std::cout << "=" << s << std::endl; } }/*}}}*/ void VCProtocol::vc_say(const QString &channel, const QString &nick, const QString &text)/*{{{*/ { PacketData p; p << VY_SAY << sndcodec->fromUnicode(channel) << 0 << sndcodec->fromUnicode(nick) << 0 << sndcodec->fromUnicode(text) << 0; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_me(const QString &channel, const QString &nick, const QString &text)/*{{{*/ { PacketData p; p << VY_ME << sndcodec->fromUnicode(channel) << 0 << sndcodec->fromUnicode(nick) << 0 << sndcodec->fromUnicode(text) << 0; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_whohere(const QString &updater)/*{{{*/ { PacketData p; p << VY_WHOHERE << sndcodec->fromUnicode(updater) << 0 << (useutf ? '1' : '0') << 0; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_imhere(const QHostAddress &addr, const QString &updater, const QString &responder, char status, char gender, char winstate)/*{{{*/ { PacketData p; p << VY_IMHERE << sndcodec->fromUnicode(updater) << 0 << sndcodec->fromUnicode(responder) << 0 << status << winstate << 0 << PROTOVERSION << gender << uuid << 0 << 0 << 0 << 0 << 0 //reserved dword << (useutf ? '1' : '0') << 0 << 0 << 0 << 0 //color << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_beep(const QHostAddress &addr, const QString& to, const QString& from)/*{{{*/ { PacketData p; p << VY_BEEP << VY_BEEP_SIGNAL << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(from) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_beepack(const QHostAddress &addr, const QString& to, const QString& from, char gender)/*{{{*/ { PacketData p; p << VY_BEEP << VY_BEEP_ACK << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << gender; send(addr, &p); }/*}}}*/ void VCProtocol::vc_changeactivity(const QString &who, char winstate)/*{{{*/ { PacketData p; p << VY_CHANGEACTIV << sndcodec->fromUnicode(who) << 0 << winstate; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_join(const QString &who, const QString &channel, char status, char gender)/*{{{*/ { PacketData p; if (channel == MAIN_CHANNEL) p << VY_JOIN << sndcodec->fromUnicode(who) << 0 << sndcodec->fromUnicode(channel) << 0 << status << gender << 0 << PROTOVERSION << uuid << (useutf ? '1' : '0') << 0xff << 0xff << 0xff << 0xff //color << 0; else p << VY_JOIN << sndcodec->fromUnicode(who) << 0 << sndcodec->fromUnicode(channel) << 0 << status << gender << 0 << (useutf ? '1' : '0') << 0; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_leave(const QString &who, const QString &channel, char gender)/*{{{*/ { PacketData p; p << VY_LEAVE << sndcodec->fromUnicode(who) << 0 << sndcodec->fromUnicode(channel) << 0 << gender; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_private_join(const QHostAddress &addr, const QString &from, const QString &to, char gender)/*{{{*/ { PacketData p; p << VY_PRIVATE << VY_PRIVATE_JOIN << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << gender; send(addr, &p); }/*}}}*/ void VCProtocol::vc_private_leave(const QHostAddress &addr, const QString &from, const QString &to, char gender)/*{{{*/ { PacketData p; p << VY_PRIVATE << VY_PRIVATE_LEAVE << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << gender; send(addr, &p); }/*}}}*/ void VCProtocol::vc_private_say(const QHostAddress &addr, const QString &from, const QString &to, const QString &text)/*{{{*/ { PacketData p; p << VY_PRIVATE << VY_PRIVATE_SAY << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(text) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_private_me(const QHostAddress &addr, const QString &from, const QString &to, const QString &text)/*{{{*/ { PacketData p; p << VY_PRIVATE << VY_PRIVATE_ME << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(text) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_message(const QHostAddress &addr, const QString &from, const QString &to, const QString &text)/*{{{*/ { PacketData p; p << VY_MESSAGE << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(text) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_massmessage(const QHostAddress &addr, const QString &from, const QString &to, const QString &text)/*{{{*/ { PacketData p; p << VY_MASSMESSAGE << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(text) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_messageack(const QHostAddress &addr, const QByteArray &sig, char status, const QString &from, const QString &to, char gender, const QString &answer)/*{{{*/ { PacketData p; p << VY_MESSAGEACK << status << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << gender << sndcodec->fromUnicode(answer) << 0 << sig << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_herereq(const QString &from, const QString &channel)/*{{{*/ { PacketData p; p << VY_HEREREQ << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(channel) << 0; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_hereack(const QHostAddress &addr, const QString &to, const QString &channel, const QString &from, char ra)/*{{{*/ { PacketData p; p << VY_HEREACK << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(channel) << 0 << sndcodec->fromUnicode(from) << 0 << ra; send(addr, &p); }/*}}}*/ void VCProtocol::vc_inforeq(const QHostAddress &addr, const QString &to, const QString &from)/*{{{*/ { PacketData p; p << VY_INFOREQ << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(from) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_inforeqack(const QHostAddress &addr, const QString &to, const QString &from, const QString &comp, const QString &name, const QString &ip, const QString &channels, const QString &answer)/*{{{*/ { PacketData p; p << VY_INFOREQACK << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(comp) << 0 << sndcodec->fromUnicode(name) << 0 << sndcodec->fromUnicode(ip) << 0 << sndcodec->fromUnicode(channels) << 0 << sndcodec->fromUnicode(answer) << 0 << sndcodec->fromUnicode(VC_PLATFORM) << 0 << sndcodec->fromUnicode(VC_SOFTWARE) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_nickchange(const QString &from, const QString &to, char gender)/*{{{*/ { PacketData p; p << VY_NICKCHANGE << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(to) << 0 << gender; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_changestatus(const QString &who, char status, char gender, const QString &answer)/*{{{*/ { PacketData p; p << VY_CHANGESTAT << sndcodec->fromUnicode(who) << 0 << status << gender << sndcodec->fromUnicode(answer) << 0; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_currenttopic(const QHostAddress &addr, const QString &to, const QString &channel, const QString &topic)/*{{{*/ { PacketData p; p << VY_CURRTOPIC << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(channel) << 0 << sndcodec->fromUnicode(topic) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_newtopic(const QString &channel, const QString &topic, const QString &who)/*{{{*/ { PacketData p; p << VY_NEWTOPIC << sndcodec->fromUnicode(channel) << 0 << sndcodec->fromUnicode(topic) << " (" << sndcodec->fromUnicode(who) << ')' << 0; send(broadcast, &p); }/*}}}*/ void VCProtocol::vc_ping(const QHostAddress &addr, const QString &to, const QString &from, const QString &time)/*{{{*/ { PacketData p; p << VY_PING << VY_PINGREQ << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(time) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_pong(const QHostAddress &addr, const QString &to, const QString &from, const QString &time)/*{{{*/ { PacketData p; p << VY_PING << VY_PINGACK << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(from) << 0 << sndcodec->fromUnicode(time) << 0; send(addr, &p); }/*}}}*/ void VCProtocol::vc_floodnotify(const QHostAddress &addr, const QString &to, const QString &from, int seconds)/*{{{*/ { PacketData p; p << VY_FLOODNOTIFY << sndcodec->fromUnicode(to) << 0 << sndcodec->fromUnicode(from) << sndcodec->fromUnicode(QString::number(seconds)) << 0; send(addr, &p); }/*}}}*/