#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#include <netinet/tcp.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#include <include/openssl/ssl.h>

/* -----------------------------------------------------------------------------
 * @brief   Performs TCP 3-way handshake with IP:PORT
 * -------------------------------------------------------------------------------- */
int connect_once(const char* IP) {

    struct sockaddr_in a;

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&a, 0, sizeof(a));
    a.sin_family = AF_INET;
    a.sin_addr.s_addr = inet_addr(IP);
    a.sin_port = htons(PORT);

    // Set socket to blocking, in order to make things simpler
    if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK )<0) {
        ERR("fcntl");
    }

    if (connect(fd, (struct sockaddr *) &a, sizeof(a))<0) {
        ERR("Econnect");
    }
    DBG("Connected");
    return fd;
}

/* -----------------------------------------------------------------------------
 * @brief   Fills the buffer with random data.
 *------------------------------------------------------------------------------ */
void fill_buffer_from_file(unsigned char *b, size_t sz) {
    FILE * fd = fopen(RANDOM_DATA_FILE, "r");
    if (!fd) {
        ERR("fopen");
    }

    if (fread(b, 1, sz, fd) < sz) {
        // Random data file smaller than a buffer
        ERR("fread");
    }

    if (fclose(fd)) {
        ERR("fclose");
    }
}

/* -----------------------------------------------------------------------------
 * @brief   Initializes BoringSSL structures
 *------------------------------------------------------------------------------ */
void init(void) {
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    SSL_library_init();
    CRYPTO_library_init();

    if(!SSL_library_init())
    {
        fprintf(stderr, "** OpenSSL initialization failed!\n");
        exit(-1);
    }
}

/* -----------------------------------------------------------------------------
 * @brief   Tears down what was initialized in init() above
 *------------------------------------------------------------------------------ */
void cleanup(void) {

    ERR_free_strings();
    ERR_clear_error();
    CRYPTO_set_locking_callback(NULL);
    CRYPTO_set_id_callback(NULL);
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
}