- Support to get/send binary data in Network::Socket
[dashstudio.git] / src / dashserver / connection.cpp
blob3da75d946e00606ca14d42b34b3a3183f97cb24f
1 /***************************************************************************
2 * Copyright (C) 2006 by David Cuadrado *
3 * krawek@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "connection.h"
23 // Qt
24 #include <QCryptographicHash>
25 #include <QQueue>
26 #include <QXmlStreamReader>
27 #include <QXmlStreamWriter>
29 // DLib
30 #include <dcore/algorithm.h>
31 #include <dcore/debug.h>
33 // Dash
34 #include <dash/network/socket.h>
36 // Dashemon
37 #include "server.h"
38 #include "logger.h"
39 #include "users/user.h"
40 #include "dash/network/package/error.h"
43 namespace DashServer {
45 class Connection::Private
47 public:
48 Private(TcpServer *server) : server(server), user(0)
52 ~Private()
54 delete client;
55 delete user;
58 Dash::Network::Socket *client;
59 DashServer::TcpServer *server;
61 bool isValid;
62 QQueue<QString> readed;
63 QHash<int, QVariant> data;
64 QString sign;
66 Users::User *user;
68 void signPackage(QDomDocument &doc);
71 void Connection::Private::signPackage(QDomDocument &doc)
73 doc.documentElement().setAttribute("sign", sign);
76 Connection::Connection(int socketDescriptor, DashServer::TcpServer *server) : QThread(server), d(new Private(server))
78 D_INIT;
80 d->client = new Dash::Network::Socket(this);
81 d->client->setSocketDescriptor(socketDescriptor);
82 connect(d->client, SIGNAL(disconnected()), this, SLOT(removeConnection()));
83 d->isValid = true;
84 d->client->addObserver(this);
87 Connection::~Connection()
89 D_END;
90 delete d;
93 void Connection::run()
95 while(! d->readed.isEmpty() )
97 if ( !d->isValid ) break;
99 if( !d->user )
100 d->isValid = false;
102 QString readed = d->readed.dequeue();
104 dDebug(/*"server"*/) << "Reicieved: " << readed;
106 QString root;
108 QXmlStreamReader reader(readed);
109 while( !reader.atEnd())
111 if( reader.readNext() == QXmlStreamReader::StartElement)
113 root = reader.name().toString();
114 break;
119 if ( !root.isEmpty() )
121 emit packageReaded(this, root, readed);
123 else
125 dError("server") << "Cannot set document content!";
131 void Connection::removeConnection()
133 emit connectionClosed(this);
136 void Connection::close()
138 d->isValid = false;
140 d->readed.clear();
141 if ( d->client->state() != QAbstractSocket::UnconnectedState )
143 d->client->flush();
145 d->client->disconnectFromHost();
146 d->client->waitForDisconnected();
147 d->client->close();
151 void Connection::readed(const QString &readed)
153 dDebug(/*"server"*/) << "Enqueing: " << readed;
154 d->readed.enqueue(readed);
156 if( ! isRunning() )
157 start();
160 void Connection::dataReaded(const QByteArray &data)
162 dfDebug << "Data readed!";
164 qFatal("Save the file!");
167 void Connection::sendToClient(const QString &xml, bool sign) const
169 if( sign )
171 d->client->send( signXml(xml).toLocal8Bit() );
173 else
175 d->client->send( xml.toLocal8Bit() );
179 void Connection::setData(int key, const QVariant &value)
181 d->data.insert(key, value);
184 QVariant Connection::data(int key) const
186 return d->data.value(key);
189 Dash::Network::Socket *Connection::client() const
191 return d->client;
194 TcpServer *Connection::server() const
196 return d->server;
199 void Connection::sendToAll(const QString &xml, bool sign)
201 emit requestSendToAll(signXml(xml));
204 void Connection::sendToClient(QDomDocument &doc, bool sign)
206 if ( sign)
207 d->signPackage(doc);
209 dDebug() << "sending " << doc.toString();
211 d->client->send(doc);
215 void Connection::sendToAll(QDomDocument &doc, bool sign)
217 if( sign )
218 d->signPackage(doc);
219 emit requestSendToAll(doc.toString(0));
222 QString Connection::sign() const
224 return d->sign;
227 QString Connection::signXml(const QString &xml) const
229 QString tosend;
231 if( !d->sign.isEmpty() )
233 QXmlStreamReader reader(xml);
234 QXmlStreamWriter writer(&tosend);
236 bool isRoot = false;
237 while( ! reader.atEnd() )
239 reader.readNext();
241 writer.writeCurrentToken(reader);
242 if( reader.tokenType() == QXmlStreamReader::StartElement && !isRoot )
244 dfDebug << "Writing sign on " << reader.name().toString();
246 if( reader.attributes().value("sign").isEmpty() )
247 writer.writeAttribute("sign", d->sign);
248 isRoot = true;
252 if ( !isRoot )
253 tosend = xml;
255 else
257 tosend = xml;
260 return tosend;
263 void Connection::setUser(Users::User *user)
265 d->user = user;
266 generateSign();
268 d->isValid = true;
271 Users::User *Connection::user() const
273 return d->user;
276 void Connection::generateSign()
278 if ( d->user )
280 d->sign =
281 QCryptographicHash::hash((d->user->login()+DCore::Algorithm::randomString(DCore::Algorithm::random() % 10)).toLocal8Bit(), QCryptographicHash::Md5).toBase64();
286 void Connection::sendError(const QString & message, Dash::Network::Package::Error::Level level)
288 Dash::Network::Package::Error error(message, level);
289 sendToClient(error.toString(), true);
292 void Connection::setValid(bool v)
294 d->isValid = v;
297 bool Connection::isValid() const
299 return d->isValid;