/*
    Copyright (C) 2010 Eduardo Robles Elvira

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "secureserver.h"
#include <QtNetwork/QSslKey>
#include <QtNetwork/QSslConfiguration>
#include <QtCore/QFile>

const qint16 port = 1025;

SecureServer::SecureServer()
{
    listen(QHostAddress::Any, port);
    qDebug() << "Listening on port " << port;
}

SecureServer::~SecureServer()
{

}

void SecureServer::incomingConnection(int socketDescriptor)
{
    QThread *thread = new SecureServerConnectionThread(socketDescriptor, this);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

/*** SecureServerConnection  and  SecureServerConnectionThread ***/

SecureServerConnectionThread::SecureServerConnectionThread(int socketDescriptor, SecureServer* parent): QThread(parent), m_socketDescriptor(socketDescriptor)
{

}

void SecureServerConnectionThread::run()
{
    new SecureServerConnection(m_socketDescriptor, 0);

    exec();
}


SecureServerConnection::SecureServerConnection(int socketDescriptor, QObject* parent)
    : QSslSocket(parent)
{
    qDebug() << "SecureServerConnection::SecureServerConnection" << socketDescriptor;

    connect(this, SIGNAL(encrypted()), this, SLOT(encrypted()));
    connect(this, SIGNAL(connected()), this, SLOT(connected()));
    connect(this, SIGNAL(disconnected()), this, SLOT(disconnected()));
    connect(this, SIGNAL(readyRead()), this, SLOT(readyRead()));
    connect(this, SIGNAL(modeChanged(QSslSocket::SslMode)), this,
        SLOT(sslModeChanged(QSslSocket::SslMode)));
    connect(this, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this,
        SLOT(stateChanged(QAbstractSocket::SocketState)));
    connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this,
        SLOT(error(QAbstractSocket::SocketError)));
    connect(this, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));

    setPrivateKey("localhost.key");
    qDebug() << "privateKey.isNull(): " << privateKey().isNull();
    setLocalCertificate("localhost.pem");
    setPeerVerifyMode(QSslSocket::VerifyPeer);
    qDebug() << "certificate.isNull(): " << localCertificate().isNull();

    if (setSocketDescriptor(socketDescriptor)) {
        qDebug() << "mode: " << mode();
        qDebug() << "state: " << state();
        qDebug() << "Calling startServerEncryption()";
        startServerEncryption();
    } else {
        qDebug() << "!!! setSocketDescriptor failed";
        deleteLater();
        return;
    }
}

SecureServerConnection::~SecureServerConnection()
{

}


void SecureServerConnection::encrypted()
{
    qDebug() << "SecureServerConnection::encrypted()";
    qDebug() << "Peer certificate: is valid? " << peerCertificate().isValid() <<
        "\nPeer certificate: CommonName: " <<
        peerCertificate().issuerInfo(QSslCertificate::CommonName) <<
        "\nPeer certificate: Organization: " <<
        peerCertificate().issuerInfo(QSslCertificate::Organization);
}

void SecureServerConnection::connected()
{
    qDebug() << "SecureServerConnection::connected()";
}

void SecureServerConnection::disconnected()
{
    qDebug() << "SecureServerConnection::disconnected() >> calling to deleteLater()";
    deleteLater();
}
void SecureServerConnection::error(QAbstractSocket::SocketError socketError)
{
    qDebug() << "SecureServerConnection::error()" << errorString();
}

void SecureServerConnection::readyRead()
{
    qDebug() << "SecureServerConnection::readyRead()";
    QTextStream stream(this);

    QString line;
    while (!(line = stream.readLine()).isNull()) {
        qDebug() << "Read from socket:" << line;
    }
}

void SecureServerConnection::sslErrors(const QList< QSslError >& errorList)
{
    qDebug() << "SecureServerConnection::sslErrors()";
    Q_FOREACH(QSslError error, errorList) {
        qDebug() << "error:" << error.errorString();
    }
}

void SecureServerConnection::sslModeChanged(QSslSocket::SslMode sslMode)
{
    qDebug() << "SecureServerConnection::sslModeChanged()" << sslMode;
}

void SecureServerConnection::stateChanged(QAbstractSocket::SocketState socketState)
{
    qDebug() << "SecureServerConnection::stateChanged()";
}

#include "secureserver.moc"
