1 /***************************************************************************
2 * Copyright (C) 2006 by David Cuadrado *
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. *
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. *
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"
24 #include <QCryptographicHash>
26 #include <QXmlStreamReader>
27 #include <QXmlStreamWriter>
30 #include <dcore/algorithm.h>
31 #include <dcore/debug.h>
34 #include <dash/network/socket.h>
39 #include "users/user.h"
40 #include "dash/network/package/error.h"
43 namespace DashServer
{
45 class Connection::Private
48 Private(TcpServer
*server
) : server(server
), user(0), finishing(false)
58 Dash::Network::Socket
*client
;
59 DashServer::TcpServer
*server
;
62 QQueue
<QString
> readed
;
63 QHash
<int, QVariant
> data
;
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
))
81 d
->client
= new Dash::Network::Socket(this);
82 d
->client
->setSocketDescriptor(socketDescriptor
);
83 connect(d
->client
, SIGNAL(disconnected()), this, SLOT(removeConnection()));
85 d
->client
->addObserver(this);
88 Connection::~Connection()
94 void Connection::run()
96 while(! d
->readed
.isEmpty() )
98 if ( !d
->isValid
) break;
103 QString readed
= d
->readed
.dequeue();
105 dDebug(/*"server"*/) << "Reicieved: " << readed
;
109 QXmlStreamReader
reader(readed
);
110 while( !reader
.atEnd())
112 if( reader
.readNext() == QXmlStreamReader::StartElement
)
114 root
= reader
.name().toString();
120 if ( !root
.isEmpty() )
122 emit
packageReaded(this, root
, readed
);
126 dError("server") << "Cannot set document content!";
132 void Connection::removeConnection()
134 emit
connectionClosed(this);
137 void Connection::close()
143 if ( d
->client
->state() != QAbstractSocket::UnconnectedState
)
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
);
162 void Connection::dataReaded(const QByteArray
&data
)
167 void Connection::sendToClient(const QString
&xml
, bool sign
) const
171 d
->client
->send( signXml(xml
).toLocal8Bit() );
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
194 TcpServer
*Connection::server() const
199 void Connection::sendToAll(const QString
&xml
, bool sign
)
201 emit
requestSendToAll(signXml(xml
));
204 void Connection::sendToClient(QDomDocument
&doc
, bool sign
)
209 dDebug() << "sending " << doc
.toString();
211 d
->client
->send(doc
);
215 void Connection::sendToAll(QDomDocument
&doc
, bool sign
)
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
236 QString
Connection::signXml(const QString
&xml
) const
240 if( !d
->sign
.isEmpty() )
242 QXmlStreamReader
reader(xml
);
243 QXmlStreamWriter
writer(&tosend
);
246 while( ! reader
.atEnd() )
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
);
272 void Connection::setUser(Users::User
*user
)
280 Users::User
*Connection::user() const
285 void Connection::generateSign()
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
)
306 bool Connection::isValid() const
311 void Connection::process()
313 if( !isRunning() && !d
->finishing
)