/*
# Copyright (c) 2010 - OpenSLX Project, Computer Center University of Freiburg
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your suggestions, praise, or complaints to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org/
# -----------------------------------------------------------------------------
# src/net/pvsMsg.cpp
# - ??? .
# -----------------------------------------------------------------------------
*/
#include "pvsMsg.h"
#include <cstring>
#include <QtNetwork/QUdpSocket>
#include <QtNetwork/QHostAddress>
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif
static unsigned char PVS_ID = 'P';
// Several constructors for the PVSMsg class...
PVSMsg::PVSMsg()
{
_msgType = PVSMESSAGE;
_buffer = NULL;
_buffLen = 0;
_buffFill = 0;
}
PVSMsg::PVSMsg(PVSMsgType type, QString ident, QString msg, int recID)
{
this->_recID = recID;
if (ident.size())
_msgIdent = ident;
else
_msgIdent = QString("invalid");
_msgType = type;
_msgString = msg;
_buffer = NULL;
_buffLen = 0;
_buffFill = 0;
}
PVSMsg::PVSMsg(PVSMsg const& copyMe)
{
_msgType = copyMe._msgType;
_msgString = copyMe._msgString;
_msgIdent = copyMe._msgIdent;
_remoteIp = copyMe._remoteIp;
_buffLen = copyMe._buffLen;
_buffFill = copyMe._buffFill;
if (_buffLen > 0)
{
_buffer = new char[_buffLen];
memcpy(_buffer, copyMe._buffer, _buffLen);
}
else
_buffer = NULL;
_sndID = copyMe._sndID;
_recID = copyMe._recID;
}
// Destructor...
PVSMsg::~PVSMsg()
{
if (_buffer)
delete[] _buffer;
}
int PVSMsg::readMessage(QAbstractSocket* sock, bool udp)
{
if (_buffFill > 0 && _buffLen <= _buffFill)
return 1;
qint64 ret = 0;
if (_buffFill < 4) // message header is not complete yet
{
if (_buffer == NULL)
{
_remoteIp = sock->peerAddress().toString();
if (udp)
_buffer = new char[1000];
else
_buffer = new char[4];
}
// Read as many bytes as needed to complete the 4 byte header
if (udp)
ret = ((QUdpSocket*)sock)->readDatagram(_buffer, 1000);
else
ret = sock->read(_buffer + _buffFill, 4 - _buffFill);
if (ret == -1) return -1;
_buffFill += (int)ret;
if (_buffFill == 0)
return 0;
if (_buffer[0] != PVS_ID)
{
// check if the id byte is correct
// otherwise either the message parsing is broken
// or someone is sending garbage
return -1;
}
if (_buffFill >= 4)
{
// header complete, allocate buffer
_buffLen = 4 + (unsigned char)_buffer[2] + (unsigned char)_buffer[3];
char *nb = new char[_buffLen + 1]; // +1 for \0
memcpy(nb, _buffer, _buffFill);
delete[] _buffer;
_buffer = nb;
}
}
if (_buffFill >= 4)
{
// got header, assemble rest of msg
if (!udp)
{
ret = sock->read(_buffer + _buffFill, _buffLen - _buffFill); // read remaining bytes
if (ret == -1) return -1;
_buffFill += (int)ret;
}
if (_buffFill >= _buffLen)
{
// message is complete
_buffer[_buffLen] = '\0'; // first, terminate with nullchar
_msgString = QString::fromUtf8(_buffer + 4 + (unsigned char)_buffer[2]); // get message
_buffer[4 + (unsigned char)_buffer[2]] = '\0';
_msgIdent = QString::fromUtf8(_buffer + 4); // get ident
_msgType = (PVSMsgType)_buffer[1]; // get msg type
return 1;
}
}
return 0;
}
void PVSMsg::setMessage(QString text)
{
_msgString = text;
}
void PVSMsg::setIdent(QString ident)
{
_msgIdent = ident;
}
QString PVSMsg::getMessage()
{
return _msgString;
}
QString PVSMsg::getIdent()
{
return _msgIdent;
}
bool PVSMsg::getBinaryData(char*& data, int& dataLen)
{
if (_msgIdent.size() == 0)
return false;
this->makeSndBuff();
data = (char*) _buffer;
dataLen = _buffLen;
return true;
}
void PVSMsg::setSndID(int id)
{
_sndID = id;
}
void PVSMsg::setRecID(int id)
{
_recID = id;
}
// Create a send buffer with the necessary size
bool PVSMsg::makeSndBuff()
{
QByteArray uIdent = _msgIdent.toUtf8();
QByteArray uString = _msgString.toUtf8();
uIdent.truncate(255);
uString.truncate(255);
_buffLen = 4 + uIdent.size() + uString.size();
if (_buffer != NULL)
delete[] _buffer;
unsigned char *tmpBuffer = new unsigned char[_buffLen + 1];
tmpBuffer[0] = PVS_ID;
tmpBuffer[1] = (unsigned char) _msgType;
tmpBuffer[2] = (unsigned char) uIdent.size();
tmpBuffer[3] = (unsigned char) uString.size();
memcpy(tmpBuffer + 4, uIdent.data(), uIdent.size());
memcpy(tmpBuffer + 4 + uIdent.size(), uString.data(), uString.size());
//printf("[%c] '%s' - '%s'\n", (char)_msgType, _msgIdent.toUtf8().data(), _msgString.toUtf8().data());
tmpBuffer[_buffLen] = '\0';
//printf("Binary: '%s'\n", _buffer);
_buffer = (char*)tmpBuffer;
return true;
}