summaryrefslogtreecommitdiffstats
path: root/chicken-wranglers/src/network/networkserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chicken-wranglers/src/network/networkserver.cpp')
-rw-r--r--chicken-wranglers/src/network/networkserver.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/chicken-wranglers/src/network/networkserver.cpp b/chicken-wranglers/src/network/networkserver.cpp
new file mode 100644
index 0000000..8f13259
--- /dev/null
+++ b/chicken-wranglers/src/network/networkserver.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** This file is a part of QtChickenWranglers.
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE."
+**
+****************************************************************************/
+
+
+#include "networkserver.h"
+
+#include "bluetoothhandler.h"
+#include "lanhandler.h"
+#include "network.h"
+#include "udphandler.h"
+
+#include <QtCore/QList>
+#include <QtCore/QTimer>
+
+NetworkServer::NetworkServer(const QString &connectivity, int discoveryTimeout, int hostAttempts, QObject *parent)
+ : QObject(parent), m_udpHandler(0), m_lanHandler(0) , m_blueHandler(0)
+ , m_discoveryAttempts(0), m_lookingForServers(true)
+ , m_discoveryTimeout(discoveryTimeout), m_discoveryHostAttempts(hostAttempts)
+ , m_serverBluetooth(true)
+{
+ createConnectionHandler(connectivity);
+}
+
+void NetworkServer::createConnectionHandler(const QString &connectivity)
+{
+ if (connectivity == "lan") {
+ m_serverBluetooth = false;
+ if (m_udpHandler)
+ return;
+
+ m_udpHandler = new UdpHandler(this);
+ m_udpHandler->setListenPort(m_lanUdpPort);
+
+ connect(m_udpHandler, SIGNAL(received(QHostAddress, QByteArray, quint16, QByteArray)),
+ this, SLOT(processUdp(QHostAddress, QByteArray, quint16, QByteArray)));
+
+ m_lanHandler = new LanHandler(this);
+ connect(m_lanHandler, SIGNAL(peerConnected(NetworkConnection *)),
+ this, SIGNAL(peerConnected(NetworkConnection *)));
+ connect(m_lanHandler, SIGNAL(peerDisconnected(NetworkConnection *)),
+ this, SIGNAL(peerDisconnected(NetworkConnection *)));
+ connect(m_lanHandler, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)),
+ this, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)));
+ connect(m_lanHandler, SIGNAL(received(NetworkMessage)),
+ this, SIGNAL(messageReceived(NetworkMessage)));
+
+ m_discoveryTimer = new QTimer(this);
+ m_discoveryTimer->setInterval(m_discoveryTimeout);
+ connect(m_discoveryTimer, SIGNAL(timeout()),
+ this, SLOT(sendDiscovery()));
+
+ } else if (connectivity == "bluetooth") {
+ m_serverBluetooth = true;
+ if (m_blueHandler)
+ return;
+
+ m_blueHandler = new BluetoothHandler(this);
+
+ connect(m_blueHandler, SIGNAL(started()),
+ this, SIGNAL(started()));
+ connect(m_blueHandler, SIGNAL(peerConnected(NetworkConnection *)),
+ this, SIGNAL(peerConnected(NetworkConnection *)));
+ connect(m_blueHandler, SIGNAL(peerDisconnected(NetworkConnection *)),
+ this, SIGNAL(peerDisconnected(NetworkConnection *)));
+ connect(m_blueHandler, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)),
+ this, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)));
+ connect(m_blueHandler, SIGNAL(received(NetworkMessage)),
+ this, SIGNAL(messageReceived(NetworkMessage)));
+ connect(m_blueHandler, SIGNAL(startError()), this, SLOT(startError()));
+ }
+}
+
+NetworkServer::~NetworkServer()
+{
+}
+
+void NetworkServer::send(const NetworkMessage &message)
+{
+ if (m_lanHandler)
+ m_lanHandler->send(message);
+ else if (m_blueHandler)
+ m_blueHandler->send(message);
+}
+
+void NetworkServer::setLanPorts(int udpPort, int tcpPort)
+{
+ m_lanUdpPort = udpPort;
+ m_lanTcpPort = tcpPort;
+}
+
+void NetworkServer::start()
+{
+ if (!m_serverBluetooth && m_lanHandler) {
+ m_udpHandler->setListenSenderType(CW::UdpSenderAny);
+ m_udpHandler->setListenPort(m_lanUdpPort + 1);
+ m_udpHandler->enable();
+ // Server tries to find if there are other
+ // running servers in the same network
+ startDiscovery();
+ } else if ((m_serverBluetooth == true) && m_blueHandler) {
+ m_blueHandler->start();
+ }
+}
+
+void NetworkServer::stop()
+{
+ if (!m_serverBluetooth && m_lanHandler) {
+ stopDiscovery();
+
+ if (m_lanHandler->isListening())
+ m_lanHandler->close();
+
+ m_udpHandler->setListenSenderType(CW::UdpSenderNoType);
+ m_udpHandler->disable();
+ } else if ((m_serverBluetooth == true) && m_blueHandler) {
+ m_blueHandler->stop();
+ }
+}
+
+void NetworkServer::closeAll()
+{
+ if (!m_serverBluetooth && m_lanHandler) {
+ stopDiscovery();
+
+ if (m_lanHandler->isListening())
+ m_lanHandler->closeAll();
+
+ m_udpHandler->setListenSenderType(CW::UdpSenderNoType);
+ m_udpHandler->disable();
+ } else if ((m_serverBluetooth == true) && m_blueHandler) {
+ m_blueHandler->closeAll();
+ }
+
+}
+
+
+void NetworkServer::startDiscovery()
+{
+ m_lookingForServers = true;
+ m_discoveryAttempts = 0;
+ m_discoveryTimer->start();
+}
+
+void NetworkServer::stopDiscovery()
+{
+ m_lookingForServers = false;
+ m_discoveryTimer->stop();
+}
+
+void NetworkServer::processUdp(QHostAddress senderAddress, QByteArray content,
+ quint16 senderListenPort, QByteArray timestamp)
+{
+ Q_UNUSED(timestamp)
+
+ quint16 contentData = content.toUShort();
+
+ if (contentData == CW::UdpContentDiscovery)
+ processDiscovery(senderAddress, senderListenPort);
+ else if (contentData == CW::UdpContentAckDiscovery)
+ processAckDiscovery(senderAddress, senderListenPort);
+}
+
+void NetworkServer::processDiscovery(QHostAddress senderAddress, quint16 senderListenPort)
+{
+ // While looking for other active servers, do not respond
+ // to Discovery messages.
+ if (m_lookingForServers)
+ return;
+
+ // Received: "Discovery" --> Send: "AckDiscovery"
+ m_udpHandler->sendDatagram(senderAddress, senderListenPort, CW::UdpSenderServer,
+ CW::UdpContentAckDiscovery, m_udpHandler->listenPort());
+}
+
+void NetworkServer::processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort)
+{
+ Q_UNUSED(senderAddress)
+ Q_UNUSED(senderListenPort)
+
+ stop();
+
+ emit error(AnotherServerRunningError);
+}
+
+void NetworkServer::sendDiscovery()
+{
+ if (m_discoveryAttempts == m_discoveryHostAttempts) {
+ stopDiscovery();
+
+ m_udpHandler->disable();
+ m_udpHandler->setListenSenderType(CW::UdpSenderAny);
+ m_udpHandler->setListenPort(m_lanUdpPort);
+ m_udpHandler->enable();
+
+ if (!m_lanHandler->isListening()) {
+ if (!m_lanHandler->listen(QHostAddress::Any, m_lanTcpPort)) {
+ startError();
+ }
+ }
+ // TODO: Return the server to the stopped state in case of port binding error.
+ if (m_udpHandler->listenPort() != m_lanUdpPort)
+ qWarning("UDP Socket error: Unable to bind to port %d", m_lanUdpPort);
+
+ started();
+ return;
+ }
+
+ m_discoveryAttempts++;
+ m_udpHandler->sendDatagram(QHostAddress::Broadcast, m_lanUdpPort,
+ CW::UdpSenderServer, CW::UdpContentDiscovery,
+ m_udpHandler->listenPort());
+}
+
+void NetworkServer::startError()
+{
+ emit error(AnotherServerRunningError);
+}