/*
* This file is a part of VyQChat.
*
* Copyright (C) 2002-2004 Pawel Stolowski <yogin@linux.bydg.org>
*
* 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 <qsocketnotifier.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
//
// 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 (;pos<p_len; pos++)
{
if (buffer[pos] == 0)
{
*str = QCString(buffer + spos);
++pos;
return true;
}
}
return false;
}/*}}}*/
bool VCProtocol::get(QString *str, char *buffer, int &pos, const int p_len, QTextCodec *tc)/*{{{*/
{
const int spos = pos;
for (;pos<p_len; pos++)
{
if (buffer[pos] == 0)
{
*str = tc->toUnicode(reinterpret_cast<char *>(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);
}/*}}}*/
syntax highlighted by Code2HTML, v. 0.9.1