static void broker_decrement_ref(BROKER_HANDLE broker)
{
    /*Codes_SRS_BROKER_13_058: [If `broker` is NULL the function shall do nothing.]*/
    if (broker != NULL)
    {
        /*Codes_SRS_BROKER_13_111: [Otherwise, Broker_Destroy shall decrement the internal ref count of the message.]*/
        /*Codes_SRS_BROKER_13_112: [If the ref count is zero then the allocated resources are freed.]*/
        if (DEC_REF(BROKER_HANDLE_DATA, broker) == DEC_RETURN_ZERO)
        {
            BROKER_HANDLE_DATA* broker_data = (BROKER_HANDLE_DATA*)broker; 
            if (singlylinkedlist_get_head_item(broker_data->modules) != NULL)
            {
                LogError("WARNING: There are still active modules attached to the broker and the broker is being destroyed.");
            }
            /* May want to do nn_shutdown first for cleanliness. */
            nn_close(broker_data->publish_socket);
            STRING_delete(broker_data->url);
            singlylinkedlist_destroy(broker_data->modules);
            Lock_Deinit(broker_data->modules_lock);
            free(broker_data);
        }
    }
    else
    {
        LogError("broker handle is NULL");
    }
}
void socketio_destroy(CONCRETE_IO_HANDLE socket_io)
{
    LIST_ITEM_HANDLE first_pending_io;

    if (socket_io != NULL)
    {
        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
        /* we cannot do much if the close fails, so just ignore the result */
        (void)closesocket(socket_io_instance->socket);

        /* clear allpending IOs */

        while ((first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list)) != NULL)
        {
            PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io);
            if (pending_socket_io != NULL)
            {
                free(pending_socket_io->bytes);
                free(pending_socket_io);
            }

            singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io);
        }

        singlylinkedlist_destroy(socket_io_instance->pending_io_list);
        if (socket_io_instance->hostname != NULL)
        {
            free(socket_io_instance->hostname);
        }

        free(socket_io);
    }
}
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 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;
}
void tls_server_io_schannel_destroy(CONCRETE_IO_HANDLE tls_io)
{
    if (tls_io != NULL)
    {
        LIST_ITEM_HANDLE first_pending_io;
        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
        if (tls_io_instance->credential_handle_allocated)
        {
            (void)FreeCredentialHandle(&tls_io_instance->credential_handle);
            tls_io_instance->credential_handle_allocated = false;
        }

        if (tls_io_instance->received_bytes != NULL)
        {
            free(tls_io_instance->received_bytes);
        }

        if (tls_io_instance->x509_schannel_handle != NULL)
        {
            x509_schannel_destroy(tls_io_instance->x509_schannel_handle);
        }

        if (tls_io_instance->x509certificate != NULL)
        {
            free(tls_io_instance->x509certificate);
        }

        if (tls_io_instance->x509privatekey != NULL)
        {
            free(tls_io_instance->x509privatekey);
        }

        xio_destroy(tls_io_instance->socket_io);
        free(tls_io_instance->host_name);

        first_pending_io = singlylinkedlist_get_head_item(tls_io_instance->pending_io_list);
        while (first_pending_io != NULL)
        {
            PENDING_SEND* pending_send = (PENDING_SEND*)singlylinkedlist_item_get_value(first_pending_io);
            if (pending_send == NULL)
            {
                LogError("Failure: retrieving socket from list");
                indicate_error(tls_io_instance);
                break;
            }
            else
            {
                if (pending_send->on_send_complete != NULL)
                {
                    pending_send->on_send_complete(pending_send->on_send_complete_context, IO_SEND_CANCELLED);
                }

                if (singlylinkedlist_remove(tls_io_instance->pending_io_list, first_pending_io) != 0)
                {
                    LogError("Failure: removing pending IO from list");
                }
            }
        }

        if (tls_io_instance->cert_context != NULL)
        {
            if (!CertFreeCertificateContext(tls_io_instance->cert_context))
            {
                LogError("Failure freeing certificate context");
            }
        }

        singlylinkedlist_destroy(tls_io_instance->pending_io_list);
        free(tls_io);
    }
}