Flush client connection
[dashstudio.git] / src / dashserver / connection.cpp
blob9ace69cebed7280374ea1f66687e5ac9aad17880
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), finishing(false)
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;
67 bool finishing;
69 void signPackage(QDomDocument &doc);
72 void Connection::Private::signPackage(QDomDocument &doc)
74 doc.documentElement().setAttribute("sign", sign);
77 Connection::Connection(int socketDescriptor, DashServer::TcpServer *server) : QThread(server), d(new Private(server))
79 D_INIT;
81 d->client = new Dash::Network::Socket(this);
82 d->client->setSocketDescriptor(socketDescriptor);
83 connect(d->client, SIGNAL(disconnected()), this, SLOT(removeConnection()));
84 d->isValid = true;
85 d->client->addObserver(this);
88 Connection::~Connection()
90 D_END;
91 delete d;
94 void Connection::run()
96 while(! d->readed.isEmpty() )
98 if ( !d->isValid ) break;
100 if( !d->user )
101 d->isValid = false;
103 QString readed = d->readed.dequeue();
105 dDebug(/*"server"*/) << "Reicieved: " << readed;
107 QString root;
109 QXmlStreamReader reader(readed);
110 while( !reader.atEnd())
112 if( reader.readNext() == QXmlStreamReader::StartElement)
114 root = reader.name().toString();
115 break;
120 if ( !root.isEmpty() )
122 emit packageReaded(this, root, readed);
124 else
126 dError("server") << "Cannot set document content!";
132 void Connection::removeConnection()
134 emit connectionClosed(this);
137 void Connection::close()
139 d->isValid = false;
140 d->finishing = true;
142 d->readed.clear();
143 if ( d->client->state() != QAbstractSocket::UnconnectedState )
145 d->client->flush();
147 d->client->disconnectFromHost();
148 d->client->waitForDisconnected();
152 void Connection::readed(const QString &readed)
154 if( d->finishing ) return;
156 dDebug(/*"server"*/) << "Enqueing: " << readed;
157 d->readed.enqueue(readed);
159 process();
162 void Connection::dataReaded(const QByteArray &data)
164 Q_UNUSED(data);
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 void Connection::sendBinaryData(const QByteArray &data)
224 d->client->setFormat(Dash::Network::Socket::Binary);
226 d->client->send(data);
228 d->client->setFormat(Dash::Network::Socket::Text);
231 QString Connection::sign() const
233 return d->sign;
236 QString Connection::signXml(const QString &xml) const
238 QString tosend;
240 if( !d->sign.isEmpty() )
242 QXmlStreamReader reader(xml);
243 QXmlStreamWriter writer(&tosend);
245 bool isRoot = false;
246 while( ! reader.atEnd() )
248 reader.readNext();
250 writer.writeCurrentToken(reader);
251 if( reader.tokenType() == QXmlStreamReader::StartElement && !isRoot )
253 dfDebug << "Writing sign on " << reader.name().toString();
255 if( reader.attributes().value("sign").isEmpty() )
256 writer.writeAttribute("sign", d->sign);
257 isRoot = true;
261 if ( !isRoot )
262 tosend = xml;
264 else
266 tosend = xml;
269 return tosend;
272 void Connection::setUser(Users::User *user)
274 d->user = user;
275 generateSign();
277 d->isValid = true;
280 Users::User *Connection::user() const
282 return d->user;
285 void Connection::generateSign()
287 if ( d->user )
289 d->sign =
290 QCryptographicHash::hash((d->user->login()+DCore::Algorithm::randomString(DCore::Algorithm::random() % 10)).toLocal8Bit(), QCryptographicHash::Md5).toBase64();
295 void Connection::sendError(const QString & message, Dash::Network::Package::Error::Level level)
297 Dash::Network::Package::Error error(message, level);
298 sendToClient(error.toString(), true);
301 void Connection::setValid(bool v)
303 d->isValid = v;
306 bool Connection::isValid() const
308 return d->isValid;
311 void Connection::process()
313 if( !isRunning() && !d->finishing )
315 start();