/* Copyright 2016. Bloomberg Finance L.P.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:  The above
 * copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
// blpapi_tlsoptions.h                                                -*-C++-*-
#ifndef INCLUDED_BLPAPI_TLSOPTIONS
#define INCLUDED_BLPAPI_TLSOPTIONS

//@PURPOSE: Maintain client credentials and trust material.
//
//@CLASSES:
//  blpapi::TlsOptions: user specified TLS options.
//
//@SEE_ALSO: blpapi_sessionoptions
//
//@DESCRIPTION: TlsOptions instances maintain client credentials and
// trust material used by a session to establish secure mutually authenticated
// connections to endpoints.
//
// The client credentials comprise an encrypted private key with a client
// certificate. The trust material comprises one or more certificates.
//
// TlsOptions objects are created using the methods
// 'TlsOptions::createFromBlobs' and 'TlsOptions::createFromFiles'; both accept
// the DER encoded client credentials in PKCS#12 format and the DER encoded
// trusted material in PKCS#7 format.
//
//
/// Usage
///-----
// The following snippet shows to use the TlsOptions when creating a
// 'SessionOptions'.
//..
// blpapi::TlsOptions tlsOptionsFromFiles
//     = blpapi::TlsOptions::createFromFiles("client",
//                                           "mypassword",
//                                           "trusted");
// tlsOptionsFromFiles.setTlsHandshakeTimeoutMs(123456);
// SessionOptions sessionOptions1;
// sessionOptions1.setTlsOptions(tlsOptionsFromFiles);
//
// std::string credentials  = getCredentials();
// std::string password     = getPassword();
// std::string trustedCerts = getCerts();
// blpapi::TlsOptions tlsOptionsFromBlobs
//     = blpapi::TlsOptions::createFromBlobs(credentials.data(),
//                                           credentials.size(),
//                                           password.c_str(),
//                                           trustedCerts.data(),
//                                           trustedCerts.size());
// tlsOptionsFromBlobs.setCrlFetchTimeoutMs(234567);
// SessionOptions sessionOptions2;
// sessionOptions2.setTlsOptions(tlsOptionsFromBlobs);
//..

#ifndef INCLUDED_BLPAPI_CALL
#include <blpapi_call.h>
#endif

#ifndef INCLUDED_BLPAPI_DEFS
#include <blpapi_defs.h>
#endif

#ifndef INCLUDED_BLPAPI_EXCEPTION
#include <blpapi_exception.h>
#endif

#ifndef INCLUDED_BLPAPI_TYPES
#include <blpapi_types.h>
#endif

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

BLPAPI_EXPORT
blpapi_TlsOptions_t *blpapi_TlsOptions_create(void);

BLPAPI_EXPORT
blpapi_TlsOptions_t *blpapi_TlsOptions_duplicate(
        const blpapi_TlsOptions_t *parameters);

BLPAPI_EXPORT
void blpapi_TlsOptions_copy(
        blpapi_TlsOptions_t *lhs, const blpapi_TlsOptions_t *rhs);

BLPAPI_EXPORT
void blpapi_TlsOptions_destroy(blpapi_TlsOptions_t *parameters);

BLPAPI_EXPORT
blpapi_TlsOptions_t *blpapi_TlsOptions_createFromFiles(
        const char *clientCredentialsFileName,
        const char *clientCredentialsPassword,
        const char *trustedCertificatesFileName);

BLPAPI_EXPORT
blpapi_TlsOptions_t *blpapi_TlsOptions_createFromBlobs(
        const char *clientCredentialsRawData,
        int clientCredentialsRawDataLength,
        const char *clientCredentialsPassword,
        const char *trustedCertificatesRawData,
        int trustedCertificatesRawDataLength);

BLPAPI_EXPORT
void blpapi_TlsOptions_setTlsHandshakeTimeoutMs(
        blpapi_TlsOptions_t *paramaters, int tlsHandshakeTimeoutMs);

BLPAPI_EXPORT
void blpapi_TlsOptions_setCrlFetchTimeoutMs(
        blpapi_TlsOptions_t *paramaters, int crlFetchTimeoutMs);

#ifdef __cplusplus
}

namespace BloombergLP {
namespace blpapi {

// ================
// class TlsOptions
// ================

class TlsOptions {
    // Contains the user specified TLS options.
    //
    // To enable SSL connections, create a TlsOptions object using the
    // methods 'TlsOptions::createFromBlobs' and 'TlsOptions::createFromFiles'.

    blpapi_TlsOptions_t *d_handle_p;

  public:
    TlsOptions();
    // Create a TlsOptions with all TLS options with no
    // certificate information.

    TlsOptions(const TlsOptions&);
    // Copy constructor

    ~TlsOptions();
    // Destroy this TlsOptions.

    // MANIPULATORS

    TlsOptions& operator=(const TlsOptions&);
    // Assign to this object the value of the specified 'rhs' object.

    static TlsOptions createFromFiles(const char *clientCredentialsFileName,
            const char *clientCredentialsPassword,
            const char *trustedCertificatesFileName);
    // Creates a TlsOptions using a DER encoded client credentials in
    // PKCS#12 format and DER encoded trust material in PKCS#7 format from
    // the specified files.

    static TlsOptions createFromBlobs(const char *clientCredentialsRawData,
            int clientCredentialsRawDataLength,
            const char *clientCredentialsPassword,
            const char *trustedCertificatesRawData,
            int trustedCertificatesRawDataLength);
    // Create a TlsOptions using DER encoded client credentials in PKCS#12
    // format and DER encoded trust material in PKCS#7 format from the
    // specified raw data.

    void setTlsHandshakeTimeoutMs(int tlsHandshakeTimeoutMs);
    // Set the TLS handshake timeout to the specified
    // 'tlsHandshakeTimeoutMs'. The default is 10,000 milliseconds.
    // The TLS handshake timeout will be set to the default if
    // the specified 'tlsHandshakeTimeoutMs' is not positive.

    void setCrlFetchTimeoutMs(int crlFetchTimeoutMs);
    // Set the CRL fetch timeout to the specified
    // 'crlFetchTimeoutMs'. The default is 20,000 milliseconds.
    // The TLS handshake timeout will be set to the default if
    // the specified 'crlFetchTimeoutMs' is not positive.

    // ACCESSORS

    blpapi_TlsOptions_t *handle() const;
    // Return the handle of the current TLS options.
};

// ============================================================================
//                      INLINE FUNCTION DEFINITIONS
// ============================================================================

// ----------------
// class TlsOptions
// ----------------
inline TlsOptions::TlsOptions()
{
    d_handle_p = BLPAPI_CALL(blpapi_TlsOptions_create)();
}

inline TlsOptions::TlsOptions(const TlsOptions& options)
{
    d_handle_p = BLPAPI_CALL(blpapi_TlsOptions_duplicate)(options.handle());
}

inline TlsOptions::~TlsOptions()
{
    BLPAPI_CALL_UNCHECKED(blpapi_TlsOptions_destroy)(d_handle_p);
}

inline TlsOptions& TlsOptions::operator=(const TlsOptions& rhs)
{
    BLPAPI_CALL(blpapi_TlsOptions_copy)(this->handle(), rhs.handle());
    return *this;
}

inline TlsOptions TlsOptions::createFromFiles(
        const char *clientCredentialsFileName,
        const char *clientCredentialsPassword,
        const char *trustedCertificatesFileName)
{
    TlsOptions tlsOptions;
    tlsOptions.d_handle_p = BLPAPI_CALL(blpapi_TlsOptions_createFromFiles)(
            clientCredentialsFileName,
            clientCredentialsPassword,
            trustedCertificatesFileName);
    return tlsOptions;
}

inline TlsOptions TlsOptions::createFromBlobs(
        const char *clientCredentialsRawData,
        int clientCredentialsRawDataLength,
        const char *clientCredentialsPassword,
        const char *trustedCertificatesRawData,
        int trustedCertificatesRawDataLength)
{
    TlsOptions tlsOptions;
    tlsOptions.d_handle_p = BLPAPI_CALL(blpapi_TlsOptions_createFromBlobs)(
            clientCredentialsRawData,
            clientCredentialsRawDataLength,
            clientCredentialsPassword,
            trustedCertificatesRawData,
            trustedCertificatesRawDataLength);
    return tlsOptions;
}

inline void TlsOptions::setTlsHandshakeTimeoutMs(int tlsHandshakeTimeoutMs)
{
    BLPAPI_CALL(blpapi_TlsOptions_setTlsHandshakeTimeoutMs)
    (d_handle_p, tlsHandshakeTimeoutMs);
}

inline void TlsOptions::setCrlFetchTimeoutMs(int crlFetchTimeoutMs)
{
    BLPAPI_CALL(blpapi_TlsOptions_setCrlFetchTimeoutMs)
    (d_handle_p, crlFetchTimeoutMs);
}

inline blpapi_TlsOptions_t *TlsOptions::handle() const { return d_handle_p; }

} // close namespace blpapi
} // close namespace BloombergLP

#endif // #ifdef __cplusplus
#endif // #ifndef INCLUDED_BLPAPI_TLSOPTIONS