/* * Copyright (C) 2012 Jason A. Donenfeld . All Rights Reserved. * * See COPYING for license information. * */ #include "JsonScgiServer.h" #include #include JsonScgiServer::JsonScgiServer(QObject *parent) : QObject(parent) { qsrand(time(0) + 42); connect(&m_listener, SIGNAL(newConnection()), this, SLOT(newConnection())); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(cleanOldSessions())); timer->setSingleShot(false); timer->start(1000 * 60 * 1); } bool JsonScgiServer::listen(const QHostAddress &address, quint16 port) { return m_listener.listen(address, port); } void JsonScgiServer::newWebRequest(const QUrl &url, QString &sessionCookie, const QVariantMap &request, JsonScgiPeer &peer) { if (sessionCookie.isEmpty()) sessionCookie = randomString(); // Create the session if there isn't one yet. if (!m_sessions.contains(sessionCookie) && m_sessions.size() > 8192) { // We abruptly cut off if there are already too many sessions. A silly way to prevent from memory DoS. peer.die(); return; } Session &session = m_sessions[sessionCookie]; if (!isSessionValid(session)) { session.expiration = QDateTime(); session.data.clear(); } if (!session.expiration.isValid() || qAbs(session.expiration.secsTo(QDateTime::currentDateTimeUtc())) < 60 * 60) session.expiration = QDateTime::currentDateTimeUtc().addSecs(60 * 60); //Default expiration: 1 hour emit webRequest(url, session, request, peer); } QDateTime JsonScgiServer::cookieExpiration(const QString &cookie) const { if (!m_sessions.contains(cookie)) return QDateTime(); return m_sessions[cookie].expiration; } QString JsonScgiServer::randomString(int size) const { static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; QString str(size, 0); for (int i = 0; i < size; ++i) // Not perfect, but I don't actually care. str[i] = alphanum[qrand() % (sizeof(alphanum) - 1)]; return str; } bool JsonScgiServer::isSessionValid(const JsonScgiServer::Session &session) const { if (session.expiration.isNull()) return false; return session.expiration > QDateTime::currentDateTimeUtc(); } void JsonScgiServer::newConnection() { while (m_listener.hasPendingConnections()) new JsonScgiPeer(m_listener.nextPendingConnection(), this); } void JsonScgiServer::cleanOldSessions() { for (QHash::iterator i = m_sessions.begin(); i != m_sessions.end();) { if (!isSessionValid(i.value()) || i.value().data.size() == 0) i = m_sessions.erase(i); else ++i; } }