/**
 *******************************************************************************
 * @brief Create a new signal message with ref count of 1.
 *
 * @param  category     IN  category
 * @param  method       IN  method (optional, NULL means none)
 * @param  payload      IN  payload
 *
 * @retval  message on success
 * @retval  NULL on failure
 *******************************************************************************
 */
_LSTransportMessage*
LSTransportMessageSignalNewRef(const char *category, const char *method, const char *payload)
{
    int category_len = strlen(category) + 1;
    int method_len = strlen(method) + 1;
    int payload_len = strlen(payload) + 1;

    LS_ASSERT(category_len > 1);
    LS_ASSERT(method_len > 1);

    _LSTransportMessage *message = _LSTransportMessageNewRef(category_len + method_len + payload_len);

    _LSTransportMessageSetType(message, _LSTransportMessageTypeSignal);

    char *message_body = _LSTransportMessageGetBody(message);

    memcpy(message_body, category, category_len);
    message_body += category_len;
    memcpy(message_body, method, method_len);
    message_body += method_len;
    memcpy(message_body, payload, payload_len);

    /* TODO: original code also appended the service_name of the sender (or "")
     * if there was no name (sh->name) */

    return message;
}
/**
 *******************************************************************************
 * @brief Send a signal registration message.
 *
 * @param  transport    IN  transport
 * @param  reg          IN  true to register, false to unregister
 * @param  category     IN  category (required)
 * @param  method       IN  method (optional, NULL means none)
 * @param  token        OUT message token
 * @param  lserror      OUT set on error
 *
 * @retval  true on success
 * @retval  false on failure
 *******************************************************************************
 */
bool
_LSTransportSignalRegistration(_LSTransport *transport, bool reg, const char *category,
                               const char *method, LSMessageToken *token, LSError *lserror)
{
    /*
     * format:
     *
     * category + NUL
     * method + NUL (if method is NULL, then we just have NUL)
     */
    bool ret = true;
    int category_len = strlen_safe(category) + 1;
    int method_len = strlen_safe(method) + 1;

    LOG_LS_TRACE("%s: category: %s, method: %s\n", __func__, category, method);

    _LSTransportMessage *message = _LSTransportMessageNewRef(category_len + method_len);

    if (reg)
    {
        _LSTransportMessageSetType(message, _LSTransportMessageTypeSignalRegister);
    }
    else
    {
        _LSTransportMessageSetType(message, _LSTransportMessageTypeSignalUnregister);
    }

    char *message_body = _LSTransportMessageGetBody(message);

    LS_ASSERT(message_body != NULL);

    memcpy(message_body, category, category_len);
    message_body += category_len;

    if (method_len == 1)
    {
        char nul = '\0';
        memcpy(message_body, &nul, sizeof(nul));
    }
    else
    {
        memcpy(message_body, method, method_len);
    }

    LS_ASSERT(transport->hub != NULL);

    if (!_LSTransportSendMessage(message, transport->hub, token, lserror))
    {
        ret = false;
    }

    _LSTransportMessageUnref(message);

    return ret;
}
static void
test_LSTransportIncoming_execute(int number_of_messages)
{
    _LSTransportIncoming *inqueue = _LSTransportIncomingNew();

    /* Is incoming message queue constructed? */
    g_assert(NULL != inqueue);
    g_assert(NULL != inqueue->complete_messages);

    /* The mutex should be initialized. */
    g_assert_cmpint(pthread_mutex_trylock(&inqueue->lock), !=, EINVAL);
    pthread_mutex_unlock(&inqueue->lock);

    _LSTransportMessage *messages[number_of_messages];
    int i;

    /* Fill queue with (possible) test data. */
    for(i = 0; i < number_of_messages; i++)
    {
        _LSTransportMessage *message = _LSTransportMessageNewRef(LS_TRANSPORT_MESSAGE_DEFAULT_PAYLOAD_SIZE);
        /* Increment ref count (possible to check message ref count after _LSTransportIncomingFree) */
        _LSTransportMessageRef(message);
        g_assert_cmpint(message->ref, ==, 2);
        messages[i] = message;

        g_queue_push_head(inqueue->complete_messages, message);
    }

    /* Simulate the message are processed */
    while (!g_queue_is_empty(inqueue->complete_messages))
    {
        _LSTransportMessage *message = g_queue_pop_head(inqueue->complete_messages);
        _LSTransportMessageUnref(message);
    }

    /* Free the struct. */
    _LSTransportIncomingFree(inqueue);

    /* The mutex should be destroyed. */
    g_assert_cmpint(pthread_mutex_trylock(&inqueue->lock), ==, EINVAL);

    /* See if the messages in the queue were unreferenced. */
    for(i = 0; i < number_of_messages; i++)
    {
        g_assert_cmpint(messages[i]->ref, ==, 1);
    }

    /* Cleanup. All testing is now over. */
    for(i = 0; i < number_of_messages; i++)
    {
        _LSTransportMessageUnref(messages[i]);
    }
}