Exemplo n.º 1
0
/**
* @brief Acquire an iterator to iterate through the subscription
*        for 'key'.
*
* @param  sh
* @param  key
* @param  *ret_iter
* @param  lserror
*
* @retval
*/
bool
LSSubscriptionAcquire(LSHandle *sh, const char *key,
                      LSSubscriptionIter **ret_iter, LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    _Catalog *catalog = sh->catalog;
    LSSubscriptionIter *iter = g_new0(LSSubscriptionIter, 1);

    _CatalogLock(catalog);
    _SubList *tokens = _CatalogGetSubList_unlocked(catalog, key);
    iter->tokens = _SubListDup(tokens);
    _CatalogUnlock(catalog);

    iter->catalog = catalog;
    iter->index = -1;
    iter->seen_messages = NULL;

    if (ret_iter)
    {
        *ret_iter = iter;
    }

    return true;
}
Exemplo n.º 2
0
/** 
* @brief Pop a message from the incoming queue, non blocking.  This should
*        only be called by custom mainloops.  Do NOT call this if you intend
*        to use callback tables registered by LSRegisterCategory().
*
*        To dispatch to callback tables use LSCustomDispatchMessage()
*        instead.
* 
* @param  sh 
* @param  *ret_message  allocated store of next message from queue, NULL if queue is empty.
*                   You MUST call LSMessageUnref() to free this message.
* @param  lserror 
* 
* @retval
*/
bool
LSCustomFetchMessage(LSHandle *sh, LSMessage **ret_message,
               LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    return _FetchMessageQueueGet(sh, ret_message, lserror);
}
Exemplo n.º 3
0
/**
* @brief Add a subscription to a list associated with 'key'.
*
* @param  sh
* @param  key
* @param  message
* @param  lserror
*
* @retval
*/
bool
LSSubscriptionAdd(LSHandle *sh, const char *key,
                  LSMessage *message, LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    return _CatalogAdd(sh->catalog, key, message, lserror);
}
Exemplo n.º 4
0
/**
* @brief Remove cancellation function callback.
*
*  Function callback removed from list not changing relative order of other elements.
*  Both function callback and context should match to remove.
*
* @param  sh
* @param  cancelNotifyFunction
* @param  ctx
* @param  lserror
*
* @retval
*/
bool LSCallCancelNotificationRemove(LSHandle *sh,
                                    LSCancelNotificationFunc cancelNotifyFunction,
                                    void *ctx, LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    return _CatalogRemoveCancelNotification(sh->catalog, cancelNotifyFunction, ctx, lserror);
}
Exemplo n.º 5
0
/** 
* @brief Wake up the user's custom mainloop.  Only works if you've
*        implented a custom mainloop via LSCustomGetFds()
* 
* @param  sh 
* @param  lserror 
* 
* @retval
*/
bool
LSCustomWakeUp(LSHandle *sh, LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    g_main_context_wakeup(sh->transport->mainloop_context);

    return true;
}
Exemplo n.º 6
0
/** 
* @brief Sets the priority level on the associated GSources for
*        the service connection. 
*
*        This should be called after LSGmainAttach().
*
*        See glib documentation for GSource priority levels.
* 
* @param  sh 
* @param  lserror 
* 
* @retval
*/
bool
LSGmainSetPriority(LSHandle *sh, int priority, LSError *lserror)
{
    _LSErrorIfFail(sh != NULL, lserror);

    LSHANDLE_VALIDATE(sh);

    return _LSTransportGmainSetPriority(sh->transport, priority, lserror);
}
Exemplo n.º 7
0
/**
* @brief Register a callback to be called when subscription cancelled.
*
*  Callback may be called when client cancels subscription via LSCallCancel()
*  or if the client drops off the bus.
*
* @param  sh
* @param  cancelFunction
* @param  ctx
* @param  lserror
*
* @retval
*/
bool
LSSubscriptionSetCancelFunction(LSHandle *sh, LSFilterFunc cancelFunction,
                                void *ctx, LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    sh->catalog->cancel_function = cancelFunction;
    sh->catalog->cancel_function_ctx = ctx;
    return true;
}
Exemplo n.º 8
0
/**
* @brief Posts a message to all in subscription '/category/method'.
*        This is equivalent to:
*        LSSubscriptionReply(sh, '/category/method', payload, lserror)
*
* @deprecated Please use LSSubscriptionReply() instead.
*
* @param  sh
* @param  category
* @param  method
* @param  payload
* @param  lserror
*
* @retval
*/
bool
LSSubscriptionPost(LSHandle *sh, const char *category,
                   const char *method,
                   const char *payload, LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    bool retVal = false;
    char *key = _LSMessageGetKindHelper(category, method);

    retVal = LSSubscriptionReply(sh, key, payload, lserror);

    g_free(key);
    return retVal;
}
Exemplo n.º 9
0
/** 
* @brief Block till incoming message is ready.  This should only be
*        called by custom mainloops.
* 
* @param  sh 
* @param  *message  allocated store of next message from queue, NULL if queue is empty.
*                   You MUST call LSMessageUnref() to free this message.
* @param  lserror 
* 
* @retval
*/
bool
LSCustomWaitForMessage(LSHandle *sh, LSMessage **message,
                               LSError *lserror)
{
    _LSErrorIfFail(sh != NULL, lserror);
    _LSErrorIfFail(message != NULL, lserror);

    LSHANDLE_VALIDATE(sh);

    bool retVal;

    /* If the incoming queue contains messages, return immediately */
    retVal = LSCustomFetchMessage(sh, message, lserror);
    if (!retVal)
        return false;
    if (*message)
        return true;
    
    /* install custom message callback if not done already */
    if (G_UNLIKELY(sh->transport->msg_handler != _LSCustomMessageHandler))
    {
        sh->transport->msg_handler = _LSCustomMessageHandler;
        sh->transport->msg_context = sh;
        
        sh->transport->mainloop_context = g_main_context_new();

        if (!sh->transport->mainloop_context)
        {
            _LSErrorSet(lserror, -ENOMEM, "OOM");
            return false;
        }

        _LSTransportAddInitialWatches(sh->transport, sh->transport->mainloop_context);
    }

    /* 
     * Run an interation of the context: g_main_context_iteration, which
     * will call our special custom message callback and add to the queue of
     * messages
     */
    g_main_context_iteration(sh->transport->mainloop_context, TRUE);

    /* Fetch 1 message off incoming queue. */
    retVal = LSCustomFetchMessage(sh, message, lserror);
    if (!retVal) return false;

    return true;
}
Exemplo n.º 10
0
/** 
* @brief Attach a service to a glib mainloop.
* 
* @param  sh 
* @param  mainLoop 
* @param  lserror 
* 
* @retval
*/
bool
LSGmainAttach(LSHandle *sh, GMainLoop *mainLoop, LSError *lserror)
{
    _LSErrorIfFail(sh != NULL, lserror);
    _LSErrorIfFail(mainLoop != NULL, lserror);

    LSHANDLE_VALIDATE(sh);

    GMainContext *context = g_main_loop_get_context(mainLoop);
    _LSErrorIfFailMsg(context != NULL, lserror, -1,
                   "%s: %s", __FUNCTION__, ": No maincontext.");

    _LSTransportGmainAttach(sh->transport, context);
    sh->context = g_main_context_ref(context);

    return true;
}
Exemplo n.º 11
0
/**
* @brief Sends a message to subscription list with name 'key'.
*
* @param  sh
* @param  key
* @param  payload
* @param  lserror
*
* @retval
*/
bool
LSSubscriptionReply(LSHandle *sh, const char *key,
                    const char *payload, LSError *lserror)
{
    LSHANDLE_VALIDATE(sh);

    bool retVal = true;
    _Catalog *catalog = sh->catalog;

    _CatalogLock(catalog);

    _SubList *tokens = _CatalogGetSubList_unlocked(catalog, key);
    if (!tokens)
    {
        retVal = true;
        goto cleanup;
    }

    int i;
    for (i = 0; i < tokens->len; i++)
    {
        char *tok = g_ptr_array_index(tokens, i);

        _Subscription *subs =
            g_hash_table_lookup(catalog->token_map, tok);
        if (!subs) continue;

        LSMessage *message = subs->message;

        retVal = LSMessageReply(sh, message, payload, lserror);
        if (!retVal) goto cleanup;
    }
cleanup:
    _CatalogUnlock(catalog);
    return retVal;
}
Exemplo n.º 12
0
/** 
* @brief Send a reply to a message using the bus identified by LSHandle.
*
*        To use the same bus upon which the message arrived, it is
*        recommended to use LSMessageRespond().
* 
* @param  sh 
* @param  lsmsg 
* @param  replyPayload 
* @param  lserror 
* 
* @retval
*/
bool
LSMessageReply(LSHandle *sh, LSMessage *lsmsg, const char *replyPayload,
                LSError *lserror)
{
    _LSErrorIfFail (sh != NULL, lserror);
    _LSErrorIfFail (lsmsg != NULL, lserror);
    _LSErrorIfFail (replyPayload != NULL, lserror);

    LSHANDLE_VALIDATE(sh);

    if (unlikely(_ls_enable_utf8_validation))
    {
        if (!g_utf8_validate (replyPayload, -1, NULL))
        {
            _LSErrorSet(lserror, -EINVAL, "%s: payload is not utf-8",
                        __FUNCTION__);
            return false;
        }
    }

    if (unlikely(strcmp(replyPayload, "") == 0))
    {
        _LSErrorSet(lserror, -EINVAL, "Empty payload is not valid JSON. Use {}");
        return false;
    }

    if (DEBUG_TRACING)
    {
        if (DEBUG_VERBOSE)
        {
                g_debug("TX: LSMessageReply token <<%ld>> %s",
                        LSMessageGetToken(lsmsg), replyPayload);
        }
        else
        {
                g_debug("TX: LSMessageReply token <<%ld>>",
                        LSMessageGetToken(lsmsg));
        }
    }

    if (_LSTransportMessageGetType(lsmsg->transport_msg) == _LSTransportMessageTypeReply)
    {
        g_warning("%s: \nYou are attempting to send a reply to a reply message.  \n"
            "I'm going to allow this for now to more easily reproduce some bugs \n"
            "we encountered with services using LSCustomWaitForMessage \n"
            "receiving a reply-to-a-reply, but soon this will return an error.",
                    __FUNCTION__);
    }

    if (unlikely(LSMessageGetConnection(lsmsg) != sh))
    {
        _LSErrorSet(lserror, -EINVAL,
            "%s: You are replying to message on different bus.\n"
            " If you can't identify which bus, "
            "try LSMessageRespond() instead.",
            __FUNCTION__);
        return false;
    }

    bool retVal = _LSTransportSendReply(lsmsg->transport_msg, replyPayload, lserror);

    return retVal;
}