1 /*******************************************************************************************************
2  DkNetwork.cpp
3  Created on:	20.07.2011
4 
5  nomacs is a fast and small image viewer with the capability of synchronizing multiple instances
6 
7  Copyright (C) 2011-2013 Markus Diem <markus@nomacs.org>
8  Copyright (C) 2011-2013 Stefan Fiel <stefan@nomacs.org>
9  Copyright (C) 2011-2013 Florian Kleber <florian@nomacs.org>
10 
11  This file is part of nomacs.
12 
13  nomacs is free software: you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  nomacs is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with this program.  If not, see <http://www.gnu.org/licenses/>.
25 
26  *******************************************************************************************************/
27 
28 #include "DkNetwork.h"
29 #include "DkSettings.h"
30 #include "DkTimer.h"
31 #include "DkControlWidget.h"	// needed for a connection
32 #include "DkUtils.h"
33 #include "DkActionManager.h"
34 
35 #pragma warning(push, 0)	// no warnings from includes - begin
36 #include <QTcpSocket>
37 #include <QStringBuilder>
38 #include <QDir>
39 #include <QNetworkInterface>
40 #include <QList>
41 #include <QThread>
42 #include <QTimer>
43 #include <QHostInfo>
44 #include <QUrl>
45 #include <QNetworkAccessManager>
46 #include <QApplication>
47 #include <QDesktopWidget>
48 #include <QMutex>
49 #include <QMutexLocker>
50 #include <QNetworkCookieJar>
51 #include <QDesktopServices>
52 #include <QDebug>
53 #include <QNetworkProxyFactory>
54 #include <QXmlStreamReader>
55 #include <QMessageBox>
56 #include <QAbstractButton>
57 #include <QProcess>
58 #include <QMimeData>
59 #include <qmath.h>
60 
61 #ifdef QT_NO_DEBUG_OUTPUT
62 #pragma warning(disable: 4127)		// no 'conditional expression is constant' if qDebug() messages are removed
63 #endif
64 
65 #pragma warning(pop)		// no warnings from includes - end
66 
67 #include <assert.h>
68 
69 namespace nmc {
70 
71 // DkClientManager --------------------------------------------------------------------
DkClientManager(const QString & title,QObject * parent)72 DkClientManager::DkClientManager(const QString& title, QObject* parent) : QObject(parent) {
73 	mNewPeerId = 0;
74 	this->mCurrentTitle = title;
75 	qRegisterMetaType<QList<quint16> >("QList<quint16>");
76 	qRegisterMetaType<QList<DkPeer*> >("QList<DkPeer*>");
77 }
78 
~DkClientManager()79 DkClientManager::~DkClientManager() {
80 
81 	// save settings
82 	sendGoodByeToAll();	// does nothing...
83 }
84 
85 
connectionReadyForUse(quint16 peerServerPort,const QString & title,DkConnection * connection)86 void DkClientManager::connectionReadyForUse(quint16 peerServerPort, const QString& title, DkConnection* connection) {
87 	//qDebug() << "connection ready for use" << connection->peerPort() << " with title:" << title << " peerServerPort:" << peerServerPort;
88 
89 	mNewPeerId++;
90 	DkPeer* peer = new DkPeer(connection->peerPort(), mNewPeerId, connection->peerAddress(), peerServerPort, title, connection, false, "", false, this);
91 	connection->setPeerId(mNewPeerId);
92 	mPeerList.addPeer(peer);
93 
94 	sendTitle(mCurrentTitle);
95 
96 }
97 
disconnected()98 void DkClientManager::disconnected() {
99 
100 	if (DkConnection *connection = qobject_cast<DkConnection *>(sender())) {
101 		removeConnection(connection);
102 	}
103 }
104 
removeConnection(DkConnection * connection)105 void DkClientManager::removeConnection(DkConnection* connection) {
106 	mPeerList.setSynchronized(connection->getPeerId(), false);
107 	emit synchronizedPeersListChanged(mPeerList.getSynchronizedPeerServerPorts());
108 
109 	auto aps = mPeerList.getActivePeers();
110 	emit clientConnectedSignal(!aps.isEmpty());
111 
112 	qDebug() << "connection Disconnected:" << connection->getPeerPort();
113 	mPeerList.removePeer(connection->getPeerId());
114 
115 	auto p = mPeerList.getPeerById(connection->getPeerId());
116 	if (p && p->isSynchronized()) {
117 		QString msg = listConnections(aps, false);
118 		emit updateConnectionSignal(msg);
119 	}
120 }
121 
connectionSentNewTitle(DkConnection * connection,const QString & newTitle)122 void DkClientManager::connectionSentNewTitle(DkConnection* connection, const QString& newTitle) {
123 	mPeerList.setTitle(connection->getPeerId(), newTitle);
124 }
125 
connectionReceivedTransformation(DkConnection *,const QTransform & transform,const QTransform & imgTransform,const QPointF & canvasSize)126 void DkClientManager::connectionReceivedTransformation(DkConnection*, const QTransform& transform, const QTransform& imgTransform, const QPointF& canvasSize) {
127 	emit receivedTransformation(transform, imgTransform, canvasSize);
128 }
129 
connectionReceivedPosition(DkConnection *,const QRect & rect,bool opacity,bool overlaid)130 void DkClientManager::connectionReceivedPosition(DkConnection*, const QRect& rect, bool opacity, bool overlaid) {
131 	emit receivedPosition(rect, opacity, overlaid);
132 }
133 
connectionReceivedNewFile(DkConnection *,qint16 op,const QString & filename)134 void DkClientManager::connectionReceivedNewFile(DkConnection*, qint16 op, const QString& filename) {
135 	emit receivedNewFile(op, filename);
136 }
137 
connectionReceivedGoodBye(DkConnection * connection)138 void DkClientManager::connectionReceivedGoodBye(DkConnection* connection) {
139 	mPeerList.removePeer(connection->getPeerId());
140 	qDebug() << "goodbye received from " << connection->getPeerId();
141 
142 	emit synchronizedPeersListChanged(mPeerList.getSynchronizedPeerServerPorts());
143 
144 	auto aps = mPeerList.getActivePeers();
145 	QString msg = listConnections(aps, false);
146 	emit updateConnectionSignal(msg);
147 	emit clientConnectedSignal(!aps.isEmpty());
148 }
149 
connectionShowStatusMessage(DkConnection *,const QString & msg)150 void DkClientManager::connectionShowStatusMessage(DkConnection*, const QString& msg) {
151 	emit sendInfoSignal(msg, 2000);
152 }
153 
sendTitle(const QString & newTitle)154 void DkClientManager::sendTitle(const QString& newTitle) {
155 	this->mCurrentTitle = newTitle;
156 
157 	QList<DkPeer*> peers = mPeerList.getPeerList();
158 	foreach (DkPeer* peer , peers) {
159 
160 		if (!peer)
161 			continue;
162 
163 		connect(this,SIGNAL(sendNewTitleMessage(const QString&)), peer->connection, SLOT(sendNewTitleMessage(const QString&)));
164 		emit sendNewTitleMessage(newTitle);
165 		disconnect(this,SIGNAL(sendNewTitleMessage(const QString&)), peer->connection, SLOT(sendNewTitleMessage(const QString&)));
166 	}
167 
168 }
169 
sendTransform(QTransform transform,QTransform imgTransform,QPointF canvasSize)170 void DkClientManager::sendTransform(QTransform transform, QTransform imgTransform, QPointF canvasSize) {
171 	QList<DkPeer*> synchronizedPeers = mPeerList.getSynchronizedPeers();
172 	foreach (DkPeer* peer , synchronizedPeers) {
173 
174 		if (!peer)
175 			continue;
176 
177 		connect(this,SIGNAL(sendNewTransformMessage(QTransform, QTransform, QPointF)), peer->connection, SLOT(sendNewTransformMessage(QTransform, QTransform, QPointF)));
178 		emit sendNewTransformMessage(transform, imgTransform, canvasSize);
179 		disconnect(this,SIGNAL(sendNewTransformMessage(QTransform, QTransform, QPointF)), peer->connection, SLOT(sendNewTransformMessage(QTransform, QTransform, QPointF)));
180 	}
181 }
182 
sendPosition(QRect newRect,bool overlaid)183 void DkClientManager::sendPosition(QRect newRect, bool overlaid) {
184 	QList<DkPeer*> synchronizedPeers = mPeerList.getSynchronizedPeers();
185 	foreach (DkPeer* peer , synchronizedPeers) {
186 
187 		if (!peer)
188 			continue;
189 
190 		connect(this,SIGNAL(sendNewPositionMessage(QRect, bool, bool)), peer->connection, SLOT(sendNewPositionMessage(QRect, bool, bool)));
191 		emit sendNewPositionMessage(newRect, true, overlaid);
192 		disconnect(this,SIGNAL(sendNewPositionMessage(QRect, bool, bool)), peer->connection, SLOT(sendNewPositionMessage(QRect, bool, bool)));
193 	}
194 }
195 
sendNewFile(qint16 op,const QString & filename)196 void DkClientManager::sendNewFile(qint16 op, const QString& filename) {
197 	QList<DkPeer*> synchronizedPeers = mPeerList.getSynchronizedPeers();
198 	foreach (DkPeer* peer , synchronizedPeers) {
199 
200 		if (!peer)
201 			continue;
202 
203 		connect(this,SIGNAL(sendNewFileMessage(qint16, const QString&)), peer->connection, SLOT(sendNewFileMessage(qint16, const QString&)));
204 		emit sendNewFileMessage(op, filename);
205 		disconnect(this,SIGNAL(sendNewFileMessage(qint16, const QString&)), peer->connection, SLOT(sendNewFileMessage(qint16, const QString&)));
206 	}
207 }
208 
newConnection(int socketDescriptor)209 void DkClientManager::newConnection( int socketDescriptor ) {
210 	DkConnection* connection = createConnection();
211 	connection->setSocketDescriptor(socketDescriptor);
212 	connection->setTitle(mCurrentTitle);
213 	mStartUpConnections.append(connection);
214 	//qDebug() << "new Connection " << connection->peerPort();
215 }
216 
connectConnection(DkConnection * connection)217 void DkClientManager::connectConnection(DkConnection* connection) {
218 	qRegisterMetaType<QList<quint16> >("QList<quint16>");
219 	connect(connection, SIGNAL(connectionReadyForUse(quint16, const QString&, DkConnection*)), this, SLOT(connectionReadyForUse(quint16, const QString& , DkConnection*)));
220 	connect(connection, SIGNAL(connectionStopSynchronize(DkConnection*)), this, SLOT(connectionStopSynchronized(DkConnection*)));
221 	connect(connection, SIGNAL(connectionStartSynchronize(QList<quint16>,DkConnection*)), this, SLOT(connectionSynchronized(QList<quint16>,DkConnection*)));
222 	connect(connection, SIGNAL(disconnected()), this, SLOT(disconnected()));
223 	connect(connection, SIGNAL(connectionTitleHasChanged(DkConnection*, const QString&)), this, SLOT(connectionSentNewTitle(DkConnection*, const QString&)));
224 	connect(connection, SIGNAL(connectionNewPosition(DkConnection*, QRect, bool, bool)), this, SLOT(connectionReceivedPosition(DkConnection*, QRect, bool, bool)));
225 	connect(connection, SIGNAL(connectionNewTransform(DkConnection*, QTransform, QTransform, QPointF)), this, SLOT(connectionReceivedTransformation(DkConnection*, QTransform, QTransform, QPointF)));
226 	connect(connection, SIGNAL(connectionNewFile(DkConnection*, qint16, const QString&)), this, SLOT(connectionReceivedNewFile(DkConnection*, qint16, const QString&)));
227 	connect(connection, SIGNAL(connectionGoodBye(DkConnection*)), this, SLOT(connectionReceivedGoodBye(DkConnection*)));
228 	connect(connection, SIGNAL(connectionShowStatusMessage(DkConnection*, const QString&)), this, SLOT(connectionShowStatusMessage(DkConnection*, const QString&)));
229 
230 	connection->synchronizedPeersListChanged(mPeerList.getSynchronizedPeerServerPorts());
231 }
232 
listConnections(QList<DkPeer * > peers,bool connected)233 QString DkClientManager::listConnections(QList<DkPeer*> peers, bool connected) {
234 
235 	QString newPeers;
236 
237 	if (!peers.empty()) {
238 		if (connected) {
239 			newPeers = tr("connected with: ");
240 		}
241 		else {
242 			newPeers = tr("disconnected with: ");
243 		}
244 
245 		newPeers.append("\n\t");
246 	}
247 
248 	for (const DkPeer* cp : peers) {
249 
250 		if (!cp->clientName.isEmpty())
251 			newPeers.append(cp->clientName);
252 		if (!cp->clientName.isEmpty() && !cp->title.isEmpty())
253 			newPeers.append(": ");
254 		if (!cp->title.isEmpty())
255 			newPeers.append(cp->title);
256 	}
257 
258 	return newPeers;
259 }
260 
sendGoodByeToAll()261 void DkClientManager::sendGoodByeToAll() {
262 
263 	foreach (DkPeer* peer, mPeerList.getPeerList()) {
264 
265 		if (!peer)
266 			continue;
267 
268 		connect(this,SIGNAL(sendGoodByeMessage()), peer->connection, SLOT(sendNewGoodbyeMessage()));
269 		emit sendGoodByeMessage();
270 		disconnect(this,SIGNAL(sendGoodByeMessage()), peer->connection, SLOT(sendNewGoodbyeMessage()));
271 	}
272 }
273 
274 // DkLocalClientManager --------------------------------------------------------------------
275 
DkLocalClientManager(const QString & title,QObject * parent)276 DkLocalClientManager::DkLocalClientManager(const QString& title, QObject* parent ) : DkClientManager(title, parent) {
277 	startServer();
278 }
279 
getPeerList()280 QList<DkPeer*> DkLocalClientManager::getPeerList() {
281 	return mPeerList.getPeerList();
282 }
283 
getServerPort() const284 quint16 DkLocalClientManager::getServerPort() const {
285 
286 	if (!mServer)
287 		return 0;
288 
289 	return mServer->serverPort();
290 }
291 
mimeData() const292 QMimeData* DkLocalClientManager::mimeData() const {
293 
294 	QByteArray connectionData;
295 	QDataStream dataStream(&connectionData, QIODevice::WriteOnly);
296 	dataStream << getServerPort();
297 
298 	QMimeData* mimeData = new QMimeData;
299 	mimeData->setData("network/sync-dir", connectionData);
300 
301 	return mimeData;
302 }
303 
startServer()304 void DkLocalClientManager::startServer() {
305 
306 	mServer = new DkLocalTcpServer(this);
307 	connect(mServer, SIGNAL(serverReiceivedNewConnection(int)), this, SLOT(newConnection(int)));
308 
309 	// TODO: hook on thread
310 	searchForOtherClients();
311 
312 	DkActionManager & am = DkActionManager::instance();
313 	connect(am.action(DkActionManager::menu_sync_connect_all), SIGNAL(triggered()), this, SLOT(connectAll()));
314 }
315 
316 // slots
connectAll()317 void DkLocalClientManager::connectAll() {
318 
319 	QList<DkPeer*> peers = getPeerList();
320 
321 	for (auto p : peers)
322 		synchronizeWithServerPort(p->peerServerPort);
323 }
324 
synchronizeWithServerPort(quint16 port)325 void DkLocalClientManager::synchronizeWithServerPort(quint16 port) {
326 	//qDebug() << "DkClientManager::synchronizeWithServerPort port:" << port;
327 	DkPeer* peer = mPeerList.getPeerByServerport(port);
328 	if (!peer)
329 		return;
330 	synchronizeWith(peer->peerId);
331 }
332 
searchForOtherClients()333 void DkLocalClientManager::searchForOtherClients() {
334 
335 	assert(mServer);
336 
337 	for (int i = local_tcp_port_start; i <= local_tcp_port_end; i++) {
338 
339 		if (i == mServer->serverPort())
340 			continue;
341 
342 		DkConnection* connection = createConnection();
343 		connection->connectToHost(QHostAddress::LocalHost, (qint16)i);
344 	}
345 }
346 
connectionSynchronized(QList<quint16> synchronizedPeersOfOtherClient,DkConnection * connection)347 void DkLocalClientManager::connectionSynchronized(QList<quint16> synchronizedPeersOfOtherClient, DkConnection* connection) {
348 
349 	qDebug() << "Connection synchronized with:" << connection->getPeerPort();
350 	mPeerList.setSynchronized(connection->getPeerId(), true);
351 	emit synchronizedPeersListChanged(mPeerList.getSynchronizedPeerServerPorts());
352 
353 	auto aps = mPeerList.getActivePeers();
354 
355 	QString msg = listConnections(aps, true);
356 	emit updateConnectionSignal(msg);
357 
358 	emit clientConnectedSignal(!aps.isEmpty());
359 
360 	for (int i = 0; i < synchronizedPeersOfOtherClient.size(); i++) {
361 
362 		if (synchronizedPeersOfOtherClient[i] != mServer->serverPort()) {
363 
364 			DkPeer* peer = mPeerList.getPeerByServerport(synchronizedPeersOfOtherClient[i]);
365 			if (!peer)
366 				continue;
367 
368 			connect(this,SIGNAL(sendSynchronizeMessage()), peer->connection, SLOT(sendStartSynchronizeMessage()));
369 			emit sendSynchronizeMessage();
370 			disconnect(this,SIGNAL(sendSynchronizeMessage()), peer->connection, SLOT(sendStartSynchronizeMessage()));
371 
372 		}
373 	}
374 	//qDebug() << "--------------------";
375 	//qDebug() << "current peer list:";
376 	//peerList.print();
377 	//qDebug() << "--------------------";
378 }
379 
connectionStopSynchronized(DkConnection * connection)380 void DkLocalClientManager::connectionStopSynchronized(DkConnection* connection) {
381 	qDebug() << "Connection no longer synchronized with: " << connection->getPeerPort();
382 	mPeerList.setSynchronized(connection->getPeerId(), false);
383 
384 	//qDebug() << "--------------------";
385 	//qDebug() << "current peer list:";
386 	//peerList.print();
387 	//qDebug() << "--------------------";
388 	emit synchronizedPeersListChanged(mPeerList.getSynchronizedPeerServerPorts());
389 
390 	auto aps = mPeerList.getActivePeers();
391 
392 	QString msg = listConnections(aps, false);
393 	emit updateConnectionSignal(msg);
394 	emit clientConnectedSignal(!aps.isEmpty());
395 }
396 
397 
synchronizeWith(quint16 peerId)398 void DkLocalClientManager::synchronizeWith(quint16 peerId) {
399 	qDebug() << "DkLocalClientManager::synchronizeWith  peerId:" << peerId;
400 
401 	mPeerList.setSynchronized(peerId, true); // will be reset if other client does not response within 1 sec
402 	emit synchronizedPeersListChanged(mPeerList.getSynchronizedPeerServerPorts());
403 
404 	DkPeer* peer = mPeerList.getPeerById(peerId);
405 	if (peer == 0 || peer->connection == 0) {
406 		//qDebug() << "TcpClient: synchronizeWith: Peer is null or connection is null";
407 		return;
408 	}
409 
410 	//qDebug() << "synchronizing with: " << peerId;
411 
412 
413 	connect(this,SIGNAL(sendSynchronizeMessage()), peer->connection, SLOT(sendStartSynchronizeMessage()));
414 	emit sendSynchronizeMessage();
415 	disconnect(this,SIGNAL(sendSynchronizeMessage()), peer->connection, SLOT(sendStartSynchronizeMessage()));
416 
417 }
418 
stopSynchronizeWith(quint16)419 void DkLocalClientManager::stopSynchronizeWith(quint16) {
420 	QList<DkPeer*> synchronizedPeers = mPeerList.getSynchronizedPeers();
421 
422 	foreach (DkPeer* peer , synchronizedPeers) {
423 
424 		if (!peer)
425 			continue;
426 
427 		connect(this,SIGNAL(sendDisableSynchronizeMessage()), peer->connection, SLOT(sendStopSynchronizeMessage()));
428 		emit sendDisableSynchronizeMessage();
429 		mPeerList.setSynchronized(peer->peerId, false);
430 		disconnect(this,SIGNAL(sendDisableSynchronizeMessage()), peer->connection, SLOT(sendStopSynchronizeMessage()));
431 	}
432 
433 	emit synchronizedPeersListChanged(mPeerList.getSynchronizedPeerServerPorts());
434 
435 	auto aps = mPeerList.getActivePeers();
436 
437 	QString msg = listConnections(aps, false);
438 	emit updateConnectionSignal(msg);
439 	emit clientConnectedSignal(!aps.isEmpty());
440 }
441 
sendArrangeInstances(bool overlaid)442 void DkLocalClientManager::sendArrangeInstances(bool overlaid) {
443 
444 	int screen = QApplication::desktop()->screenNumber(DkUtils::getMainWindow());
445 	const QRect screenGeometry =  QApplication::desktop()->availableGeometry(screen);
446 	int connectedInstances = mPeerList.getSynchronizedPeers().size() + 1 ; // +1 because of this instance itself
447 	if (connectedInstances == 1)
448 		return;
449 	int instancesPerRow = (connectedInstances == 2 || connectedInstances == 4) ? 2 : 3;
450 
451 	int rows = (int)qCeil((float)connectedInstances / (float)instancesPerRow);
452 	int width = screenGeometry.width() / instancesPerRow;
453 	int height = screenGeometry.height() / rows;
454 
455 	int curX = screenGeometry.topLeft().x();
456 	int curY = screenGeometry.topLeft().y();
457 	emit receivedPosition(QRect(curX, curY, width, height), false, overlaid);
458 	curX += width;
459 	int count = 1;
460 	for (DkPeer* peer : mPeerList.getSynchronizedPeers()) {
461 
462 		if (!peer)
463 			continue;
464 
465 		QRect newPosition = QRect(curX, curY, width, height);
466 		connect(this,SIGNAL(sendNewPositionMessage(QRect, bool, bool)), peer->connection, SLOT(sendNewPositionMessage(QRect, bool, bool)));
467 		emit sendNewPositionMessage(newPosition, false, overlaid);
468 		disconnect(this,SIGNAL(sendNewPositionMessage(QRect, bool, bool)), peer->connection, SLOT(sendNewPositionMessage(QRect, bool, bool)));
469 
470 		count++;
471 		if (count < instancesPerRow)
472 			curX += width;
473 		else {
474 			curX = screenGeometry.topLeft().x();
475 			curY += height;
476 			count = 0;
477 		}
478 	}
479 }
480 
sendQuitMessageToPeers()481 void DkLocalClientManager::sendQuitMessageToPeers() {
482 	emit sendQuitMessage();
483 }
484 
connectToNomacs()485 void DkLocalClientManager::connectToNomacs() {
486 
487 	DkConnection* c = static_cast<DkConnection*>(QObject::sender());
488 
489 	if (c) {
490 		c->sendGreetingMessage(mCurrentTitle);
491 		mStartUpConnections.append(c);
492 	}
493 
494 }
495 
connectionReceivedQuit()496 void DkLocalClientManager::connectionReceivedQuit() {
497 	emit receivedQuit();
498 }
499 
createConnection()500 DkLocalConnection* DkLocalClientManager::createConnection() {
501 
502 	// wow - there is no one owning connection (except for QOBJECT)
503 	DkLocalConnection* connection = new DkLocalConnection(this);
504 	connection->setLocalTcpServerPort(mServer->serverPort());
505 	connection->setTitle(mCurrentTitle);
506 	connectConnection(connection);
507 	connect(this, SIGNAL(synchronizedPeersListChanged(QList<quint16>)), connection, SLOT(synchronizedPeersListChanged(QList<quint16>)));
508 	connect(this, SIGNAL(sendQuitMessage()), connection, SLOT(sendQuitMessage()));
509 	connect(connection, SIGNAL(connectionQuitReceived()), this, SLOT(connectionReceivedQuit()));
510 	connect(connection, SIGNAL(connected()), this, SLOT(connectToNomacs()));
511 
512 	return connection;
513 
514 }
515 
516 // DkLocalTcpServer --------------------------------------------------------------------
DkLocalTcpServer(QObject * parent)517 DkLocalTcpServer::DkLocalTcpServer(QObject* parent) : QTcpServer(parent) {
518 
519 	for (int i = local_tcp_port_start; i < local_tcp_port_end; i++) {
520 		if (listen(QHostAddress::LocalHost, (quint16)i)) {
521 			break;
522 		}
523 	}
524 	//qDebug() << "TCP Listening on port " << this->serverPort();
525 }
526 
incomingConnection(qintptr socketDescriptor)527 void DkLocalTcpServer::incomingConnection(qintptr socketDescriptor) {
528 	emit serverReiceivedNewConnection((int)socketDescriptor);
529 	//qDebug() << "Server: NEW CONNECTION AVAIABLE";
530 }
531 
DkPeer(quint16 port,quint16 peerId,const QHostAddress & hostAddress,quint16 peerServerPort,const QString & title,DkConnection * connection,bool sychronized,const QString & clientName,bool showInMenu,QObject * parent)532 DkPeer::DkPeer(
533 	quint16 port,
534 	quint16 peerId,
535 	const QHostAddress& hostAddress,
536 	quint16 peerServerPort,
537 	const QString& title,
538 	DkConnection* connection,
539 	bool sychronized,
540 	const QString& clientName,
541 	bool showInMenu,
542 	QObject* parent) : QObject(parent) {
543 
544 	this->peerId = peerId;
545 	this->localServerPort = port;
546 	this->peerServerPort = peerServerPort;
547 	this->hostAddress = hostAddress;
548 	this->title = title;
549 	this->sychronized = sychronized;
550 	this->connection = connection;
551 	this->timer = new QTimer(this);
552 	timer->setSingleShot(true);
553 	this->clientName = clientName;
554 	this->showInMenu = showInMenu;
555 	mHasChangedRecently = false;
556 	connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeout()), Qt::UniqueConnection);
557 }
558 
~DkPeer()559 DkPeer::~DkPeer() {
560 }
561 
setSynchronized(bool flag)562 void DkPeer::setSynchronized(bool flag) {
563 	sychronized = flag;
564 	mHasChangedRecently = true;
565 	connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeout()), Qt::UniqueConnection);
566 	timer->start(1000);
567 }
568 
operator ==(const DkPeer & peer) const569 bool DkPeer::operator==(const DkPeer& peer) const {
570 
571 	return localServerPort == peer.localServerPort && sychronized == peer.sychronized && title == peer.title && hostAddress == peer.hostAddress;
572 }
573 
timerTimeout()574 void DkPeer::timerTimeout() {
575 	mHasChangedRecently = false;
576 }
577 
578 // DkPeerList --------------------------------------------------------------------
DkPeerList()579 DkPeerList::DkPeerList() {
580 	// do nothing
581 }
582 
addPeer(DkPeer * peer)583 bool DkPeerList::addPeer(DkPeer* peer) {
584 
585 	if (!peer) {
586 		qDebug() << "[WARNING] you try to append a NULL peer!";
587 		return false;
588 	}
589 
590 	if (peerList.contains(peer->peerId))
591 		return false;
592 	else {
593 		peerList.insert(peer->peerId, peer);
594 		return true;
595 	}
596 }
597 
removePeer(quint16 peerId)598 bool DkPeerList::removePeer(quint16 peerId) {
599 	if (!peerList.contains(peerId))
600 		return false;
601 	else {
602 		peerList.remove(peerId);
603 		return true;
604 	}
605 }
606 
setSynchronized(quint16 peerId,bool synchronized)607 bool DkPeerList::setSynchronized(quint16 peerId, bool synchronized) {
608 
609 	if (!peerList.contains(peerId))
610 		return false;
611 	DkPeer* peer = peerList.value(peerId);
612 	peer->setSynchronized(synchronized);
613 	//peerList.replace(peerId, peer);
614 
615 	return true;
616 }
617 
setTitle(quint16 peerId,const QString & title)618 bool DkPeerList::setTitle(quint16 peerId, const QString& title) {
619 	if (!peerList.contains(peerId))
620 		return false;
621 	DkPeer* peer = peerList.value(peerId);
622 	peer->title = title;
623 	//peerList.replace(peerId, peer);
624 
625 	return true;
626 }
627 
setShowInMenu(quint16 peerId,bool showInMenu)628 bool DkPeerList::setShowInMenu(quint16 peerId, bool showInMenu) {
629 	if (!peerList.contains(peerId))
630 		return false;
631 	DkPeer* peer = peerList.value(peerId);
632 	peer->showInMenu = showInMenu;
633 	//peerList.replace(peerId, peer);
634 
635 	return true;
636 }
637 
getSynchronizedPeers() const638 QList<DkPeer*> DkPeerList::getSynchronizedPeers() const {
639 	QList<DkPeer*> sychronizedPeers;
640 	foreach(DkPeer* peer, peerList) {
641 		if (peer->isSynchronized())
642 			sychronizedPeers.push_back(peer);
643 	}
644 	return sychronizedPeers;
645 }
646 
getPeerList()647 QList<DkPeer*> DkPeerList::getPeerList() {
648 	return peerList.values();
649 }
650 
getSynchronizedPeerServerPorts() const651 QList<quint16> DkPeerList::getSynchronizedPeerServerPorts() const {
652 	QList<quint16> sychronizedPeerServerPorts;
653 	foreach(DkPeer* peer, peerList) {
654 		if (peer->isSynchronized())
655 			sychronizedPeerServerPorts.push_back(peer->peerServerPort);
656 	}
657 	return sychronizedPeerServerPorts;
658 }
659 
getActivePeers() const660 QList<DkPeer*> DkPeerList::getActivePeers() const {
661 	QList<DkPeer*> activePeers;
662 	foreach(DkPeer* peer, peerList) {
663 		if (peer->isActive())
664 			activePeers.push_back(peer);
665 	}
666 	return activePeers;
667 }
668 
getPeerByServerport(quint16 port) const669 DkPeer* DkPeerList::getPeerByServerport(quint16 port) const {
670 	foreach (DkPeer* peer, peerList) {
671 		if (peer->peerServerPort == port)
672 			return peer;
673 	}
674 	return 0;
675 }
676 
alreadyConnectedTo(const QHostAddress & address,quint16 port) const677 bool DkPeerList::alreadyConnectedTo(const QHostAddress& address, quint16 port) const {
678 	foreach (DkPeer* peer, peerList) {
679 		if (peer->hostAddress == address && peer->localServerPort == port ) // TODO: wieso localserver port ... aber es funkt
680 			return true;
681 	}
682 	return false;
683 }
684 
getPeerById(quint16 id)685 DkPeer* DkPeerList::getPeerById(quint16 id) {
686 	return peerList.value(id, 0);
687 }
688 
getPeerByAddress(const QHostAddress & address,quint16 port) const689 DkPeer* DkPeerList::getPeerByAddress(const QHostAddress& address, quint16 port) const {
690 	foreach (DkPeer* peer, peerList) {
691 		if (peer->hostAddress == address && peer->localServerPort == port)
692 			return peer;
693 	}
694 	return 0; // should not happen
695 }
696 
print() const697 void DkPeerList::print() const {
698 	foreach (DkPeer* peer, peerList) {
699 
700 		if (!peer)
701 			continue;
702 
703 		qDebug() << peer->peerId << " " << peer->clientName << " " << peer->hostAddress << " serverPort:" << peer->peerServerPort <<
704 			" localPort:" << peer->localServerPort << " " << peer->title << " sync:" << peer->isSynchronized() << " menu:" << peer->showInMenu << " connection:" << peer->connection;
705 	}
706 }
707 
708 // DkStatusBarManager --------------------------------------------------------------------
DkSyncManager()709 DkSyncManager::DkSyncManager() {
710 
711 	DkTimer dt;
712 	mClient = new DkLocalClientManager("nomacs | Image Lounge", 0);
713 
714 	//connect(this, SIGNAL(syncWithSignal(quint16)), mClient, SLOT(synchronizeWith(quint16)));
715 	//connect(this, SIGNAL(stopSyncWithSignal(quint16)), mClient, SLOT(stopSynchronizeWith(quint16)));
716 	qInfo() << "local client created in: " << dt;	// takes 1 sec in the client thread
717 }
718 
inst()719 DkSyncManager& DkSyncManager::inst() {
720 
721 	static DkSyncManager inst;
722 	return inst;
723 }
724 
client()725 DkClientManager* DkSyncManager::client() {
726 
727 	if (!mClient) {
728 		qWarning() << "DkSyncManager::client() which is not created yet...";
729 		return 0;
730 	}
731 
732 	return mClient;
733 }
734 
735 }
736