defuze.me  Client
networkcore.cpp
00001 /**************************************************************************
00002 ** defuze.me Epitech Innovative Project
00003 **
00004 ** Copyright 2010
00005 **   Athena Calmettes - Jocelyn De La Rosa - Francois Gaillard
00006 **   Adrien Jarthon - Alexandre Moore - Luc Peres - Arnaud Sellier
00007 **
00008 ** All rights reserved.
00009 **************************************************************************/
00010 
00011 #include <QHostInfo>
00012 #include "guicore.hpp"
00013 #include "networkcore.hpp"
00014 #include "exception.hpp"
00015 #include "parser.hpp"
00016 #include "logger.hpp"
00017 #include "loginview.hpp"
00018 #include "authview.hpp"
00019 #include "status.hpp"
00020 
00021 using namespace Network;
00022 
00023 NetworkCore::NetworkCore(QStringList &)
00024 {
00025     webManager = new QNetworkAccessManager();
00026     rcServer = new QTcpServer();
00027     adServer = new QUdpSocket();
00028     authenticator = NULL;
00029     doorman = NULL;
00030 }
00031 
00032 NetworkCore::~NetworkCore()
00033 {
00034     delete rcServer;
00035     delete webManager;
00036     delete adServer;
00037 }
00038 
00039 void    NetworkCore::init(Cores *c)
00040 {
00041     JsonParser::test();
00042 
00043     cores = c;
00044 
00045     // Web service
00046     authenticator = new Authenticator(*this);
00047     authenticator->setParamsBackEnd(cores->db());
00048     authenticator->registerToParamsCore(cores->params());
00049     connect(authenticator, SIGNAL(needCredentials(const QString&)), SLOT(giveCredentials(const QString&)));
00050     connect(authenticator, SIGNAL(authenticated()), SIGNAL(APIAuthenticated()));
00051     authenticator->getToken();
00052 
00053     // Remote control
00054     initRCServer(gl_RC_PORT);
00055 
00056     // Auto discovery
00057     adServer->bind(gl_AD_ASK_PORT, QUdpSocket::ShareAddress);
00058     connect(adServer, SIGNAL(readyRead()), this, SLOT(discoveryRequest()));
00059 }
00060 
00061 void    NetworkCore::aboutToQuit()
00062 {
00063     if (authenticator)
00064         delete authenticator;
00065     if (doorman)
00066         delete doorman;
00067 }
00068 
00069 void    NetworkCore::initRCServer(unsigned short port)
00070 {
00071     if (!rcServer->listen(QHostAddress::Any, port))
00072     {
00073         Logger::log(QString("Network: RCServer could not listen port %1").arg(port));
00074         Notification::Status::gMessage(tr("Could not listen TCP port %1, launched twice or firewall?").arg(port), Notification::ERR);
00075     }
00076 
00077     if (!doorman)
00078     {
00079         doorman = new Doorman(rcServer);
00080         doorman->setParamsBackEnd(cores->db());
00081         doorman->registerToParamsCore(cores->params());
00082         connect(doorman, SIGNAL(authenticatedRemote(RemoteSock*)), SIGNAL(newRemoteClient(RemoteSock*)));
00083         connect(doorman, SIGNAL(needAuthorization(const RemoteEvent&)), SLOT(giveAuthorization(const RemoteEvent&)));
00084     }
00085 }
00086 
00087 
00088 void    NetworkCore::discoveryRequest()
00089 {
00090     while (adServer->hasPendingDatagrams())
00091     {
00092         QByteArray      datagram;
00093         QHostAddress    sender;
00094         quint16         senderPort;
00095 
00096         datagram.resize(adServer->pendingDatagramSize());
00097         adServer->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
00098         if (datagram == "\"defuze.me:discovery\"")
00099         {
00100             Logger::log("Network: new discovery request from " + sender.toString());
00101             QUdpSocket().writeDatagram(JsonParser().serialize(discoveryAddresses()), QHostAddress::Broadcast, gl_AD_REPLY_PORT);
00102         }
00103         else
00104         {
00105             Logger::log("Network: bad udp request from " + sender.toString());
00106         }
00107     }
00108 }
00109 
00110 QVariantList    NetworkCore::discoveryAddresses() const
00111 {
00112     QVariantList    list;
00113     QString         host = QHostInfo::localHostName();
00114     QVariantMap     address;
00115 
00116     address["host"] = host;
00117     address["port"] = gl_RC_PORT;
00118     QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
00119     for (int i = 0; i < ipAddressesList.size(); ++i)
00120         if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
00121             ipAddressesList.at(i) != QHostAddress::LocalHostIPv6)
00122         {
00123             address["ip"] = ipAddressesList.at(i).toString();
00124             address["protocol"] = (ipAddressesList.at(i).protocol() ? "IPv6" : "IPv4");
00125             list << address;
00126         }
00127     if (list.isEmpty())
00128     {
00129         address["ip"] = QHostAddress(QHostAddress::LocalHost).toString();
00130         list << address;
00131     }
00132     return list;
00133 }
00134 
00135 
00136 void    NetworkCore::invalidateWebToken()
00137 {
00138     authenticator->invalidate();
00139 }
00140 
00141 QVariantMap     NetworkCore::getRadioInfo() const
00142 {
00143     if (authenticator)
00144         return authenticator->getRadioInfo();
00145     else
00146         return QVariantMap();
00147 }
00148 
00149 void    NetworkCore::giveCredentials(const QString& login)
00150 {
00151     LoginView *lv = new LoginView(login);
00152 
00153     // This slot is called when the authenticator ask for credentials,
00154     // it displays a window.
00155     authenticator->connect(lv, SIGNAL(authenticate(QString, QString)), SLOT(authenticate(QString, QString)));
00156     authenticator->connect(lv, SIGNAL(cancelled()), SLOT(cancel()));
00157     lv->connect(authenticator, SIGNAL(failed(QString)), SLOT(login_failed(QString)));
00158     lv->connect(authenticator, SIGNAL(authenticated()), SLOT(login_sucess()));
00159     cores->gui()->popup(lv);
00160 }
00161 
00162 void    NetworkCore::giveAuthorization(const RemoteEvent& event)
00163 {
00164     AuthView *av = new AuthView(event);
00165 
00166     // This slot is called when the doorman ask for authorization,
00167     // it displays a window.
00168     doorman->connect(av, SIGNAL(answered(RemoteSock*, unsigned, bool, bool)), SLOT(answered(RemoteSock*, unsigned, bool, bool)));
00169     cores->gui()->popup(av);
00170 }
00171 
00172 const QString NetworkCore::name()
00173 {
00174     return "Network";
00175 }
00176 
00177 QNetworkAccessManager&  NetworkCore::web()
00178 {
00179     return *webManager;
00180 }
00181 
00182 QTcpServer&             NetworkCore::remoteControl()
00183 {
00184     return *rcServer;
00185 }
00186 
00187 QUdpSocket&             NetworkCore::autoDiscovery()
00188 {
00189     return *adServer;
00190 }
00191 
00192 // This is our default API parser, all parsing & serialization must be done using this method
00193 // This way we can easily switch our entire application API format.
00194 const Parser&           NetworkCore::apiParser() const
00195 {
00196     return defaultApiParser;
00197 }
00198 
00199 QNetworkRequest         NetworkCore::apiRequest(const QString& url) const
00200 {
00201     QNetworkRequest request;
00202     QUrl            fullUrl("http://" + gl_API_HOSTNAME + "/" + url);
00203 
00204     request.setUrl(fullUrl);
00205     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
00206     request.setRawHeader("Accept", "application/json");
00207     request.setRawHeader("Connection", "Close");
00208     request.setRawHeader("User-Agent", QString("%1 client %2").arg(gl_APPLICATION_NAME, gl_APPLICATION_VERSION).toUtf8());
00209     request.setRawHeader("Client-Version", gl_APPLICATION_VERSION.toUtf8());
00210     request.setRawHeader("API-Token", authenticator->getToken().toUtf8());
00211 
00212     Logger::log(QString("Network: new API request on %1").arg(fullUrl.toString()));
00213 
00214     return request;
00215 }