/*
 * This file is part of the KFTPGrabber project
 *
 * Copyright (C) 2003-2006 by the KFTPGrabber developers
 * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net>
 *
 * 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 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
 * NON-INFRINGEMENT.  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, write to the Free Software
 * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * file(s) with this exception, you may extend this exception to your
 * version of the file(s), but you are not obligated to do so.  If you
 * do not wish to do so, delete this exception statement from your
 * version.  If you delete this exception statement from all source
 * files in the program, then also delete it here.
 */
#ifndef KFTPENGINESSL_H
#define KFTPENGINESSL_H

#include <kstreamsocket.h>
#include <ksslcertificate.h>
#include <ksslpkcs12.h>

namespace KFTPEngine {

/**
 * This class contains information about the currently established SSL
 * connection.
 *
 * @author Jernej Kos
 */
class SslConnectionInfo {
friend class Ssl;
public:
    /**
     * Get the cipher in use.
     */
    const QString &getCipher() const { return m_cipherName; }
    
    /**
     * Describe the cipher in use.
     */
    const QString &getCipherDescription() const { return m_cipherDescription; }
    
    /**
     * Get the version of the cipher in use.
     */
    const QString &getCipherVersion() const { return m_cipherVersion; }
    
    /**
     * Get the number of bits of the cipher that are actually used.
     */
    int getCipherUsedBits() const { return m_cipherUsedBits; }
    
    /**
     * Get bit-size of the cipher.
     */
    int getCipherBits() const { return m_cipherBits; }
protected:
    /**
     * Class constructor.
     */
    SslConnectionInfo() {}
    
    int m_cipherUsedBits;
    int m_cipherBits;
    
    QString m_cipherName;
    QString m_cipherDescription;
    QString m_cipherVersion;
};

/**
 * A class that properly handles asynchronious SSL connections.
 *
 * @author Jernej Kos
 */
class Ssl {
public:
    /**
     * Class constructor.
     *
     * @param socket The socket to use as transport
     */
    Ssl(KNetwork::KStreamSocket *socket);
    
    /**
     * Class destructor.
     */
    ~Ssl();
    
    /**
     * Start the SSL handshake. This method will block until the
     * handshake is completed.
     *
     * @return True if the handshake was successful, false otherwise
     */
    bool connect();
    
    /**
     * Close the SSL connection and deallocate resources.
     */
    void close();
    
    /**
     * Read from the underlying socket.
     *
     * @param buffer The tarrget buffer
     * @param bytes Maximum number of bytes to read
     * @return Number of bytes actually read or -1 in case of an error
     */
    int read(void *buffer, int bytes);
    
    /**
     * Write to the underlying socket.
     *
     * @param buffer The source buffer
     * @param bytes Number of bytes to write
     * @return Number of bytes actually written or -1 in case of an error
     */
    int write(void *buffer, int bytes);
    
    /**
     * Obtain a reference to the connection information.
     *
     * @return A reference ot the connection information, valid after connected
     */
    SslConnectionInfo &connectionInfo();
    
    /**
     * Set the client certificate to use.
     *
     * @return True if the certificate was successfuly set
     */
    bool setClientCertificate(KSSLPKCS12 *pkcs);
private:
    class Private;
    Private *d;
    
    KNetwork::KStreamSocket *m_socket;
    SslConnectionInfo m_connectionInfo;
protected:
    /**
     * Initialize the SSL session for operation.
     */
    void initialize();
    
    /**
     * Populate the connection info object with data retrieved from the SSL
     * socket. Note that the socket has to be connected!
     */
    void setConnectionInfo();
};

}

#endif
