-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.cpp
110 lines (84 loc) · 3.45 KB
/
client.cpp
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
105
106
107
108
109
110
#include "client.h"
/* there are 5 modes FROM CLIENT (all NON-negative):
* 0 : client blockchain is broken -> server sends its blockchain
* 1 : client wants server hash -> server sends its hash
* 2 : client is sending hash -> server compares (sends all good if everything matches, else its blockchain)
* 3 : client is sending blocks -> new blocks added, server appends to end of blockchain and sends its hash
* 4 : client is sending entire blockchain -> server checks sent blockchain for errors and compares it to other nodes (if all good, uses that blockchain)
*/
/* there are 4 modes FROM SERVER (all NON-positive):
* 0 : Server + client blockchain is up to date
* -1 : Server sends hash
* -2 : Server sends its blockchain
* -100 : Error has occured
*/
Client::Client(quint16 port): serverPort(port) {}
Client::~Client() {}
Package Client::talk(const QString &hostName, quint16 port, qint8 theMode, const QByteArray& theData)
{
const int Timeout = 8 * 1000;
QTcpSocket socket;
socket.connectToHost(hostName, port);
connect(&socket, SIGNAL(disconnected()), &socket, SLOT(deleteLater()));
// cerr << "Attempted connection in client::talk\n";
if (!socket.waitForConnected(Timeout)) {
emit error(socket.error(), socket.errorString(), hostName, port);
// cerr << "throwing error in client...\n";
return Package("Error has occured", -100);
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << (quint64) 0;
out << (quint8) TRANSFERMODE;
out << serverPort;
out << theMode;
// cerr << QString::number(theMode).toStdString() << endl;
if (theMode > 1) {
out << theData;
// cerr << theData.toStdString() << endl;
}
out.device()->seek(0);
out << (quint64)(block.size() - sizeof(quint64));
// cerr << (quint64)(block.size() - sizeof(quint64)) << endl;
if(socket.state() == QAbstractSocket::ConnectedState) {
socket.write(block);
}
if (!socket.waitForBytesWritten(Timeout)) {
emit error(socket.error(), socket.errorString(), hostName, port);
// cerr << "throwing error in client...\n";
return Package("Error has occured", -100);
}
while (socket.bytesAvailable() < (quint64)sizeof(quint64)) {
if (!socket.waitForReadyRead(2 * Timeout)) {
// cerr << "In the socket.bytesAvail loop (3rd one)\n";
emit error(socket.error(), socket.errorString(), hostName, port);
// cerr << "throwing error in client...\n";
return Package("Error has occured", -100);
}
}
// cerr << "out of the socket.bytesAvail loop (3rd one)\n";
quint64 blockSize;
QDataStream in(&socket);
in >> blockSize;
// cerr << blockSize << endl;
while (socket.bytesAvailable() < blockSize) {
if (!socket.waitForReadyRead(2 * Timeout)) {
emit error(socket.error(), socket.errorString(), hostName, port);
// cerr << "throwing error in client...\n";
return Package("Error has occured", -100);
}
}
qint8 serverMode;
in >> serverMode;
// cerr << QString::number(serverMode).toStdString() << endl;
if ((!serverMode) || (serverMode == -100)) {
if (!serverMode) {
emit addConnection(hostName, port);
}
return Package("", serverMode);
}
QByteArray blockchain;
in >> blockchain;
emit addConnection(hostName, port);
return Package(blockchain, serverMode);
}