summaryrefslogblamecommitdiffstats
path: root/src/net/pvsMsg.cpp
blob: b56c97973e493e65cb59c5dcb36f0047839817a9 (plain) (tree)














































































































































































































                                                                                                               
/*
 # 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;
}