summaryrefslogtreecommitdiffstats
path: root/src/net/mcast/McastSender.cpp
blob: f49c0df5ac637eb71ab223d14fddae3eb22676fc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
# Copyright (c) 2009 - 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/mcast/McastReceiver.h
#    - implement the receiver-side multicast file transfer protocol -- implementation
# -----------------------------------------------------------------------------
*/

#include "McastSender.h"
#include "McastConstants.h"

#include <QDataStream>

#include <pgm/pgm.h>
// OpenPGM #defines bool. This is bad in C++.
#undef bool

McastSender::McastSender(QIODevice* iodev, McastConfiguration const* config, QObject* parent) :
    QObject(parent),
    _config(config ? new McastConfiguration(*config) : new McastConfiguration()),
    _socket(0),
    _iodev(iodev),
    _curoffs(0),
    _hash(QCryptographicHash::Md5),
    _finished(false)
{
}

McastSender::~McastSender()
{
	delete _config;
}

void McastSender::start()
{
    _socket = new McastPGMSocket(this);
    connect(_socket, SIGNAL(readyToSend()), this, SLOT(readyToSend()));
    _socket->open(_config, McastPGMSocket::PSOCK_WRITE);
}

void McastSender::readyToSend()
{
	if(_finished)
		return;

    if(_iodev->atEnd())
    {
        QByteArray fpdu;
        QDataStream strm(&fpdu, QIODevice::WriteOnly);
        strm.setByteOrder(QDataStream::BigEndian);

        strm << (quint64)MCASTFT_MAGIC << (quint64)UINT64_C(0xffffffffffffffff) << _hash.result();
        strm << qChecksum(fpdu.constData(), fpdu.size());

        _socket->sendPacket(fpdu);
        connect(_socket, SIGNAL(connectionFinished()), this, SLOT(socketFinished()));
        _socket->shutdown();

        _finished = true;

        _iodev->close();
    }
    else
    {
		QByteArray barr(DEFAULT_MULTICAST_APDU, '\0');
		qint64 len_read;
		len_read = _iodev->read(barr.data(), barr.capacity());
		barr.resize((int)len_read);

		_hash.addData(barr);

		QByteArray pdu;
		QDataStream strm(&pdu, QIODevice::WriteOnly);
		strm.setByteOrder(QDataStream::BigEndian);

		strm << (quint64)MCASTFT_MAGIC << _curoffs;
		strm << barr;
		quint16 checksum = qChecksum(pdu.constData(), pdu.size());
		strm << checksum;

		_curoffs += len_read;

		_socket->sendPacket(pdu);
    }
}

void McastSender::close()
{
	_socket->finish();
}

void McastSender::socketFinished()
{
	delete _socket;
	emit finished();
}