/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */

/**
 * @file iotcs_port_ssl.h
 * @brief The file contains porting layer for ssl functionality.
 */

#ifndef IOTCS_PORT_SSL_H
#define IOTCS_PORT_SSL_H

#ifdef __cplusplus
extern "C" {
#endif

#include "iotcs.h"

    /**
     * @file iotcs_port_ssl.h
     * @brief Methods for SSL/TLS protocol
     * Library always calls iotcs_port_ssl_init before start using port SSL API
     * and iotcs_port_ssl_finalize when has stopped using port SSL API.
     * 
     * Port SSL API always shall support at least one SSL connection.
     * Library works with this connection by calling blocking methods
     * iotcs_port_ssl_connect, iotcs_port_ssl_write, iotcs_port_ssl_read,
     * iotcs_port_ssl_disconnect. This is the order in which library calls those
     * methods. The whole connect/write/read/disconnect sequence is invoked from
     * one thread and always exclusively. It means that implementation does not
     * require thread safety.
     * 
     * Library could be built with long polling support by defining
     * IOTCS_LONG_POLLING. Without long polling support library use just one
     * SSL connection at a time. Long polling support adds another connection.
     * Methods that work with this long polling connection have _lp suffix, e.g.
     * iotcs_port_ssl_connect_lp. The whole connect/write/read/disconnect
     * sequence for long polling connection is invoked from one thread and
     * always exclusively. But usual connection and long polling connection
     * could be used by library at same time from different threads.
     */

#define IOTCS_RESULT_SSL_WANT_READ IOTCS_RESULT_CANNOT_AUTHORIZE

    /**
     * @brief Initializes ssl related resources
     * @note Mandatory API. Called by the Library in any configuration.
     * @param addr server address
     * @param port server port
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_ssl_init(const char* addr, unsigned short port);

    /**
     * @brief Finalizes ssl related resources
     * @note Mandatory API. Called by the Library in any configuration.
     */
    void iotcs_port_ssl_finalize(void);

    /**
     * @brief Establishes ssl connection with the server
     * @note Mandatory API. Called by the Library in any configuration.
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_ssl_connect(void);

    /**
     * @brief Closes connection with the server
     * @note Mandatory API. Called by the Library in any configuration.
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_ssl_disconnect(void);

    /**
     * @brief Sends content to the server host using ssl connection
     * @note Mandatory API. Called by the Library in any configuration.
     * @param request a buffer address
     * @param length a buffer size in bytes
     * @return IOTCS_RESULT_OK when the complete contents of request with current length has been written.
     */
    iotcs_result iotcs_port_ssl_write(char* request, size_t length);

    /**
     * @brief Reads all bytes from the ssl connection into the buffer
     * Do blocking read of all the bytes from established connection until given
     * buffer is full or the connection is closed by peer.
     * @note Mandatory API. Called by the Library in any configuration.
     * @param buffer a buffer address
     * @param len a buffer size in bytes
     * @param bytes_read  read bytes
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned.
     */
    iotcs_result iotcs_port_ssl_read(char* buffer, int len, int *bytes_read);

#if defined IOTCS_LONG_POLLING || defined IOTCS_DOXYGEN
    /**
     * @brief Establishes ssl connection with the server for long polling
     * @note Optional API. Called by the Library if IOTCS_LONG_POLLING option is defined.
     * @param timeout a receive timeout in milliseconds
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_ssl_connect_lp(int32_t timeout_ms);

    /**
     * @brief Closes long polling connection with the server
     * @note Optional API. Called by the Library if IOTCS_LONG_POLLING option is defined.
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_ssl_disconnect_lp(void);

    /**
     * @brief Sends content to the server host using long polling ssl connection
     * @note Optional API. Called by the Library if IOTCS_LONG_POLLING option is defined.
     * @param request a buffer address
     * @param length a buffer size in bytes
     * @return IOTCS_RESULT_OK when the complete contents of request with current length has been written.
     */
    iotcs_result iotcs_port_ssl_write_lp(char* request, size_t length);

    /**
     * @brief Reads all bytes from the long polling ssl connection into the buffer
     * Do blocking read of all the bytes from established connection until given
     * buffer is full or the connection is closed by peer or the receive timeout
     * (given in iotcs_port_ssl_connect_lp call) has expired.
     * @note Optional API. Called by the Library if IOTCS_LONG_POLLING option is defined.
     * @param buffer a buffer address
     * @param len a buffer size in bytes
     * @param bytes_read  read bytes
     * @return IOTCS_RESULT_OK if socket closed by peer or buffer is full.
     *  IOTCS_RESULT_SSL_WANT_READ if timeout has expired. IOTCS_RESULT_FAIL in
     *  case of error.
     */
    iotcs_result iotcs_port_ssl_read_lp(char* buffer, int len, int *bytes_read);
#endif

#if defined IOTCS_STORAGE_SUPPORT || defined IOTCS_DOXYGEN
    /**
     * @brief Initializes ssl related resources
     * @note Optional API. Called by the Library when STORAGE_SUPPORT enabled.
     * @param addr scs server address
     * @param port scs server port
     * @param is_ssl shows which type of server is using (https or http)
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_storage_ssl_init(const char* addr, unsigned short port, iotcs_bool is_ssl);

    /**
     * @brief Finalizes ssl related resources
     * @note Optional API. Called by the Library when STORAGE_SUPPORT enabled.
     */
    void iotcs_port_storage_ssl_finalize(void);

    /**
     * @brief Establishes ssl connection with the storage cloud server
     * @note Optional API. Called by the Library when STORAGE_SUPPORT enabled.
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_storage_ssl_connect(void);

    /**
     * @brief Closes the connection with the storage cloud server
     * @note Optional API. Called by the Library when STORAGE_SUPPORT enabled.
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned
     */
    iotcs_result iotcs_port_storage_ssl_disconnect(void);

    /**
     * @brief Reads all bytes from the storage cloud server ssl connection into the buffer
     * Do blocking read of all the bytes from established connection until given
     * buffer is full or the connection is closed by peer.
     * @note Optional API. Called by the Library when STORAGE_SUPPORT enabled.
     * @param buffer a buffer address
     * @param len a buffer size in bytes
     * @param bytes_read  read bytes
     * @return IOTCS_RESULT_OK on success; otherwise error result code will be returned.
     */
    iotcs_result iotcs_port_storage_ssl_read(char* buffer, int len, int *bytes_read);

    /**
     * @brief Sends content to the storage cloud server.
     * @note Optional API. Called by the Library when STORAGE_SUPPORT enabled.
     * @param request a buffer address
     * @param length a buffer size in bytes
     * @return IOTCS_RESULT_OK when the complete contents of request with current length has been written.
     */
    iotcs_result iotcs_port_storage_ssl_write(char* request, size_t length);
#endif

#ifdef __cplusplus
}
#endif

#endif /* IOTCS_PORT_SSL_H */

