static CONCRETE_IO_HANDLE tlsio_cyclonessl_create()

in archive/cyclonessl/tlsio_cyclonessl.c [123:251]


static CONCRETE_IO_HANDLE tlsio_cyclonessl_create(void* io_create_parameters)
{
    TLS_IO_INSTANCE* result;

    /* Codes_SRS_TLSIO_CYCLONESSL_01_002: [ If io_create_parameters is NULL, tlsio_cyclonessl_create shall fail and return NULL. ]*/
    if (io_create_parameters == NULL)
    {
        result = NULL;
        LogError("NULL tls_io_config.");
    }
    else
    {
        /* Codes_SRS_TLSIO_CYCLONESSL_01_003: [ io_create_parameters shall be used as a TLSIO_CONFIG\*. ]*/
        TLSIO_CONFIG* tls_io_config = io_create_parameters;

        /* Codes_SRS_TLSIO_CYCLONESSL_01_004: [ If the hostname member is NULL, then tlsio_cyclonessl_create shall fail and return NULL. ]*/
        if (tls_io_config->hostname == NULL)
        {
            result = NULL;
            LogError("NULL hostname in the TLS IO configuration.");
        }
        else
        {
            result = malloc(sizeof(TLS_IO_INSTANCE));
            if (result == NULL)
            {
                /* Codes_SRS_TLSIO_CYCLONESSL_01_076: [ If allocating memory for the TLS IO instance fails then tlsio_cyclonessl_create shall fail and return NULL. ]*/
                LogError("Failed allocating TLSIO instance.");
            }
            else
            {
                uint8_t seed[32];
                size_t i;

                /* Codes_SRS_TLSIO_CYCLONESSL_01_005: [ tlsio_cyclonessl_create shall copy the hostname and port values for later use when the open of the underlying socket is needed. ]*/
                /* Codes_SRS_TLSIO_CYCLONESSL_01_006: [ hostname shall be copied by calling mallocAndStrcpy_s. ]*/
                if (mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname) != 0)
                {
                    /* Codes_SRS_TLSIO_CYCLONESSL_01_007: [ If mallocAndStrcpy_s fails then tlsio_cyclonessl_create shall fail and return NULL. ]*/
                    /* Codes_SRS_TLSIO_CYCLONESSL_01_018: [ When tlsio_cyclonessl_create fails, all allocated resources up to that point shall be freed. ]*/
                    LogError("Failed to copy the hostname.");
                    free(result);
                    result = NULL;
                }
                else
                {
                    result->port = tls_io_config->port;
                    result->certificate = NULL;
                    result->on_bytes_received = NULL;
                    result->on_bytes_received_context = NULL;
                    result->on_io_error = NULL;
                    result->on_io_error_context = NULL;
                    result->tlsio_state = TLSIO_STATE_NOT_OPEN;
                    result->socket = (TlsSocket)NULL;

                    /* seed should be initialized with some random seed ... */
                    for (i = 0; i < 32; i++)
                    {
                        seed[i] = rand() * 255 / RAND_MAX;
                    }

                    /* Codes_SRS_TLSIO_CYCLONESSL_01_008: [ tlsio_cyclonessl_create shall initialize the yarrow context by calling yarrowInit. ]*/
                    if (yarrowInit(&result->yarrowContext) != NO_ERROR)
                    {
                        /* Codes_SRS_TLSIO_CYCLONESSL_01_009: [ If yarrowInit fails then tlsio_cyclonessl_create shall return NULL. ]*/
                        /* Codes_SRS_TLSIO_CYCLONESSL_01_018: [ When tlsio_cyclonessl_create fails, all allocated resources up to that point shall be freed. ]*/
                        LogError("yarrowInit failed");
                        free(result->hostname);
                        free(result);
                        result = NULL;
                    }
                    /* Codes_SRS_TLSIO_CYCLONESSL_01_010: [ The yarrow context shall be seeded with 32 bytes of randomly chosen data by calling yarrowSeed. ]*/
                    else if (yarrowSeed(&result->yarrowContext, seed, sizeof(seed)) != NO_ERROR)
                    {
                        /* Codes_SRS_TLSIO_CYCLONESSL_01_011: [ If yarrowSeed fails then tlsio_cyclonessl_create shall return NULL. ]*/
                        /* Codes_SRS_TLSIO_CYCLONESSL_01_018: [ When tlsio_cyclonessl_create fails, all allocated resources up to that point shall be freed. ]*/
                        LogError("yarrowInit seed failed");
                        yarrowRelease(&result->yarrowContext);
                        free(result->hostname);
                        free(result);
                        result = NULL;
                    }
                    else
                    {
                        /* Codes_SRS_TLSIO_CYCLONESSL_01_012: [ tlsio_cyclonessl_create shall create a TLS context by calling tlsInit. ]*/
                        result->tlsContext = tlsInit();
                        if (result->tlsContext == NULL)
                        {
                            /* Codes_SRS_TLSIO_CYCLONESSL_01_013: [ If tlsInit fails then tlsio_cyclonessl_create shall return NULL. ]*/
                            /* Codes_SRS_TLSIO_CYCLONESSL_01_018: [ When tlsio_cyclonessl_create fails, all allocated resources up to that point shall be freed. ]*/
                            tlsFree(result->tlsContext);
                            yarrowRelease(&result->yarrowContext);
                            free(result->hostname);
                            free(result);
                            LogError("Creating the TLS context failed");
                            result = NULL;
                        }
                        /* Codes_SRS_TLSIO_CYCLONESSL_01_014: [ The TLS context shall be setup to operate as a client by calling tlsSetConnectionEnd with TLS_CONNECTION_END_CLIENT. ]*/
                        else if (tlsSetConnectionEnd(result->tlsContext, TLS_CONNECTION_END_CLIENT))
                        {
                            /* Codes_SRS_TLSIO_CYCLONESSL_01_015: [ If tlsSetConnectionEnd fails then tlsio_cyclonessl_create shall return NULL. ]*/
                            /* Codes_SRS_TLSIO_CYCLONESSL_01_018: [ When tlsio_cyclonessl_create fails, all allocated resources up to that point shall be freed. ]*/
                            tlsFree(result->tlsContext);
                            yarrowRelease(&result->yarrowContext);
                            free(result->hostname);
                            free(result);
                            LogError("tlsSetConnectionEnd failed");
                            result = NULL;
                        }
                        /* Codes_SRS_TLSIO_CYCLONESSL_01_016: [ The pseudo random number generator to be used shall be set by calling tlsSetPrng with the yarrow instance as argument. ]*/
                        else if (tlsSetPrng(result->tlsContext, YARROW_PRNG_ALGO, &result->yarrowContext) != NO_ERROR)
                        {
                            /* Codes_SRS_TLSIO_CYCLONESSL_01_017: [ If tlsSetPrng fails then tlsio_cyclonessl_create shall return NULL. ]*/
                            /* Codes_SRS_TLSIO_CYCLONESSL_01_018: [ When tlsio_cyclonessl_create fails, all allocated resources up to that point shall be freed. ]*/
                            tlsFree(result->tlsContext);
                            yarrowRelease(&result->yarrowContext);
                            free(result->hostname);
                            free(result);
                            LogError("tlsSetPrng failed");
                            result = NULL;
                        }
                    }
                }
            }
        }
    }

    return result;
}