CONCRETE_IO_HANDLE socketio_create(void* io_create_parameters)
{
    SOCKETIO_CONFIG* socket_io_config = io_create_parameters;
    SOCKET_IO_INSTANCE* result;
    struct tcp_keepalive tcp_keepalive = { 0, 0, 0 };

    if (socket_io_config == NULL)
    {
        LogError("Invalid argument: socket_io_config is NULL");
        result = NULL;
    }
    else
    {
        result = malloc(sizeof(SOCKET_IO_INSTANCE));
        if (result != NULL)
        {
            result->pending_io_list = singlylinkedlist_create();
            if (result->pending_io_list == NULL)
            {
                LogError("Failure: singlylinkedlist_create unable to create pending list.");
                free(result);
                result = NULL;
            }
            else
            {
                if (socket_io_config->hostname != NULL)
                {
                    result->hostname = (char*)malloc(strlen(socket_io_config->hostname) + 1);
                    if (result->hostname != NULL)
                    {
                        (void)strcpy(result->hostname, socket_io_config->hostname);
                    }

                    result->socket = INVALID_SOCKET;
                }
                else
                {
                    result->hostname = NULL;
                    result->socket = *((SOCKET*)socket_io_config->accepted_socket);
                }

                if ((result->hostname == NULL) && (result->socket == INVALID_SOCKET))
                {
                    LogError("Failure: hostname == NULL and socket is invalid.");
                    singlylinkedlist_destroy(result->pending_io_list);
                    free(result);
                    result = NULL;
                }
                else
                {
                    result->port = socket_io_config->port;
                    result->on_bytes_received = NULL;
                    result->on_io_error = NULL;
                    result->on_bytes_received_context = NULL;
                    result->on_io_error_context = NULL;
                    result->io_state = IO_STATE_CLOSED;
                    result->keep_alive = tcp_keepalive;

                }
            }
        }
        else
        {
            LogError("Allocation Failure: SOCKET_IO_INSTANCE");
        }
    }

    return (XIO_HANDLE)result;
}
BROKER_HANDLE Broker_Create(void)
{
    BROKER_HANDLE_DATA* result;

    /*Codes_SRS_BROKER_13_067: [Broker_Create shall malloc a new instance of BROKER_HANDLE_DATA and return NULL if it fails.]*/
    result = REFCOUNT_TYPE_CREATE(BROKER_HANDLE_DATA);
    if (result == NULL)
    {
        LogError("malloc returned NULL");
        /*return as is*/
    }
    else
    {
        /*Codes_SRS_BROKER_13_007: [Broker_Create shall initialize BROKER_HANDLE_DATA::modules with a valid VECTOR_HANDLE.]*/
        result->modules = singlylinkedlist_create();
        if (result->modules == NULL)
        {
            /*Codes_SRS_BROKER_13_003: [This function shall return NULL if an underlying API call to the platform causes an error.]*/
            LogError("VECTOR_create failed");
            free(result);
            result = NULL;
        }
        else
        {
            /*Codes_SRS_BROKER_13_023: [Broker_Create shall initialize BROKER_HANDLE_DATA::modules_lock with a valid LOCK_HANDLE.]*/
            result->modules_lock = Lock_Init();
            if (result->modules_lock == NULL)
            {
                /*Codes_SRS_BROKER_13_003: [This function shall return NULL if an underlying API call to the platform causes an error.]*/
                LogError("Lock_Init failed");
                singlylinkedlist_destroy(result->modules);
                free(result);
                result = NULL;
            }
            else
            {
                /*Codes_SRS_BROKER_17_001: [ Broker_Create shall initialize a socket for publishing messages. ]*/
                result->publish_socket = nn_socket(AF_SP, NN_PUB);
                if (result->publish_socket < 0)
                {
                    /*Codes_SRS_BROKER_13_003: [ This function shall return NULL if an underlying API call to the platform causes an error. ]*/
                    LogError("nanomsg puclish socket create failedL %d", result->publish_socket);
                    singlylinkedlist_destroy(result->modules);
                    Lock_Deinit(result->modules_lock);
                    free(result);
                    result = NULL;
                }
                else
                {
                    result->url = construct_url();
                    if (result->url == NULL)
                    {
                        /*Codes_SRS_BROKER_13_003: [ This function shall return NULL if an underlying API call to the platform causes an error. ]*/
                        singlylinkedlist_destroy(result->modules);
                        Lock_Deinit(result->modules_lock);
                        nn_close(result->publish_socket);
                        free(result);
                        LogError("Unable to generate unique url.");
                        result = NULL;
                    }
                    else
                    {
                        /*Codes_SRS_BROKER_17_004: [ Broker_Create shall bind the socket to the BROKER_HANDLE_DATA::url. ]*/
                        if (nn_bind(result->publish_socket, STRING_c_str(result->url)) < 0)
                        {
                            /*Codes_SRS_BROKER_13_003: [ This function shall return NULL if an underlying API call to the platform causes an error. ]*/
                            LogError("nanomsg bind failed");
                            singlylinkedlist_destroy(result->modules);
                            Lock_Deinit(result->modules_lock);
                            nn_close(result->publish_socket);
                            STRING_delete(result->url);                
                            free(result);
                            result = NULL;
                        }
                    }
                }
            }
        }
    }

    /*Codes_SRS_BROKER_13_001: [This API shall yield a BROKER_HANDLE representing the newly created message broker. This handle value shall not be equal to NULL when the API call is successful.]*/
    return result;
}
CONCRETE_IO_HANDLE tls_server_io_schannel_create(void* io_create_parameters)
{
    TLS_SERVER_IO_CONFIG* tls_server_io_config = (TLS_SERVER_IO_CONFIG*)io_create_parameters;
    TLS_IO_INSTANCE* result;

    if (tls_server_io_config == NULL)
    {
        LogError("invalid argument detected: void* io_create_parameters = %p", tls_server_io_config);
        result = NULL;
    }
    else
    {
        result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
        if (result == NULL)
        {
            LogError("malloc failed");
        }
        else
        {
            HCERTSTORE cert_store_handle;
            const IO_INTERFACE_DESCRIPTION* underlying_io_interface;
            void* io_interface_parameters;

            result->on_bytes_received = NULL;
            result->on_io_open_complete = NULL;
            result->on_io_close_complete = NULL;
            result->on_io_error = NULL;
            result->on_io_open_complete_context = NULL;
            result->on_io_close_complete_context = NULL;
            result->on_bytes_received_context = NULL;
            result->on_io_error_context = NULL;
            result->credential_handle_allocated = false;
            result->x509_schannel_handle = NULL;
            result->needed_bytes = 0;

            /* A cert store called "My" has to be available for use ...
            This is because this is only used in a test now ... */
            cert_store_handle = CertOpenStore(CERT_STORE_PROV_SYSTEM,
                X509_ASN_ENCODING,
                0,
                CERT_SYSTEM_STORE_LOCAL_MACHINE,
                L"MY");

            if (cert_store_handle == NULL)
            {
                result->cert_context = NULL;
                LogError("Error opening store for server.");
            }
            else
            {
                result->cert_context = CertFindCertificateInStore(cert_store_handle,
                    X509_ASN_ENCODING,
                    0,
                    CERT_FIND_SUBJECT_STR_A,
                    "localhost", // use appropriate subject name
                    NULL
                );

                if (!CertCloseStore(cert_store_handle, 0))
                {
                    LogError("Error closing store.");
                }
            }

            underlying_io_interface = tls_server_io_config->underlying_io_interface;
            io_interface_parameters = tls_server_io_config->underlying_io_parameters;

            if (underlying_io_interface == NULL)
            {
                LogError("socketio_get_interface_description failed");
                free(result->host_name);
                free(result);
                result = NULL;
            }
            else
            {
                result->socket_io = xio_create(underlying_io_interface, io_interface_parameters);
                if (result->socket_io == NULL)
                {
                    LogError("xio_create failed");
                    free(result->host_name);
                    free(result);
                    result = NULL;
                }
                else
                {
                    result->pending_io_list = singlylinkedlist_create();
                    if (result->pending_io_list == NULL)
                    {
                        LogError("Failed creating pending IO list.");
                        xio_destroy(result->socket_io);
                        free(result->host_name);
                        free(result);
                        result = NULL;
                    }
                    else
                    {
                        result->received_bytes = NULL;
                        result->received_byte_count = 0;
                        result->buffer_size = 0;
                        result->tlsio_state = TLS_SERVER_IO_STATE_NOT_OPEN;
                        result->x509certificate = NULL;
                        result->x509privatekey = NULL;
                        result->x509_schannel_handle = NULL;
                    }
                }
            }
        }
    }

    return result;
}