Exemplo n.º 1
0
bool
LSGmainAttachPalmService(LSPalmService *psh,
                           GMainLoop *mainLoop, LSError *lserror)
{
    _LSErrorIfFail(psh != NULL, lserror);
    _LSErrorIfFail(mainLoop != NULL, lserror);

    bool retVal;
    retVal = LSGmainAttach(psh->public_sh, mainLoop, lserror);
    if (!retVal) return retVal;
    retVal = LSGmainAttach(psh->private_sh, mainLoop, lserror);
    if (!retVal) return retVal;

    return retVal;
}
Exemplo n.º 2
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.º 3
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.º 4
0
/** 
* @brief Get the unique serial of this message.  Do not confuse with
* LSMessageGetResponseToken().
* 
* @param  message 
* 
* @retval
*/
LSMessageToken
LSMessageGetToken(LSMessage *message)
{
    _LSErrorIfFail(NULL != message, NULL);

    LSMessageToken serial = _LSTransportMessageGetToken(message->transport_msg);
    return serial;
}
Exemplo n.º 5
0
/** 
* @brief Obtain a unique token identifying the sender.
* 
* @param  message 
* 
* @retval
*/
const char *
LSMessageGetSender(LSMessage *message)
{
    _LSErrorIfFail(NULL != message, NULL);

    const char *sender = _LSTransportMessageGetSenderUniqueName(message->transport_msg);

    return sender;
}
Exemplo n.º 6
0
/** 
* @brief Get the name of the service that sent the message. (NULL if the
* sender didn't register a service name)
* 
* @param  message 
* 
* @retval   service_name if service sending the message has a name
* @retval   NULL otherwise
*/
const char *
LSMessageGetSenderServiceName(LSMessage *message)
{
    _LSErrorIfFail(NULL != message, NULL);

    const char *service_name = _LSTransportMessageGetSenderServiceName(message->transport_msg);

    return service_name;
}
Exemplo n.º 7
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.º 8
0
/** 
 * @brief Detach a service from a glib mainloop. You should NEVER use this
 * function unless you are fork()'ing without exec()'ing and know what you are
 * doing. This will perform nearly all the same cleanup as LSUnregister(), with
 * the exception that it will not send out shutdown messages or flush any
 * buffers. It is intended to be used only when fork()'ing so that your child
 * process can continue without interfering with the parent's file descriptors,
 * since open file descriptors are duplicated during a fork().
 * 
 * @param  sh 
 * @param  lserror 
 * 
 * @retval
 */
bool
LSGmainDetach(LSHandle *sh, LSError *lserror)
{
    _LSErrorIfFail(sh != NULL, lserror);
    _LSErrorIfFailMsg(sh->context != NULL, lserror, -1,
                      "%s: %s", __FUNCTION__, ": No maincontext.");

    /* We "unregister" without actually flushing or sending shutdown messages */
    return _LSUnregisterCommon(sh, false, LSHANDLE_GET_RETURN_ADDR(), lserror);
}
Exemplo n.º 9
0
/** 
* @brief Get the method name of the message.
* 
* @param  message 
* 
* @retval
*/
const char *
LSMessageGetMethod(LSMessage *message)
{
    _LSErrorIfFail(NULL != message, NULL);

    if (message->method) return message->method;

    message->method = _LSTransportMessageGetMethod(message->transport_msg);

    return message->method;
}
Exemplo n.º 10
0
/** 
* @brief Get the category of this message.
* 
* @param  message 
* 
* @retval
*/
const char *
LSMessageGetCategory(LSMessage *message)
{
    _LSErrorIfFail(NULL != message, NULL);

    if (message->category)
        return message->category;

    message->category = _LSTransportMessageGetCategory(message->transport_msg);

    return message->category;
}
Exemplo n.º 11
0
/** 
* @brief Get the response token associated with this message this will match
* with the LSMessageGetToken() of the original call.
*
* For signals, the response token is supplanted with the original token
* returned from LSSignalCall().
* 
* @param  reply
* 
* @retval
*/
LSMessageToken
LSMessageGetResponseToken(LSMessage *reply)
{
    _LSErrorIfFail(NULL != reply, NULL);

    if (reply->responseToken)
        return reply->responseToken;

    reply->responseToken = _LSTransportMessageGetReplyToken(reply->transport_msg);

    return reply->responseToken;
}
Exemplo n.º 12
0
/** 
* @brief Convenience function to pretty print a message.
* 
* @param  lmsg 
* @param  out 
* 
* @retval
*/
bool
LSMessagePrint(LSMessage *message, FILE *out)
{
    _LSErrorIfFail(NULL != message, NULL);

    fprintf(out, "%s/%s <%s>\n",
        LSMessageGetCategory(message),
        LSMessageGetMethod(message),
        LSMessageGetPayload(message));

    return true;
}
Exemplo n.º 13
0
/** 
* @brief Get the payload of this message.
* 
* @param  message 
* 
* @retval
*/
const char *
LSMessageGetPayload(LSMessage *message)
{
    _LSErrorIfFail(message != NULL, NULL);

    if (message->payload)
    {
        return message->payload;
    }

    message->payload = _LSTransportMessageGetPayload(message->transport_msg);

    return message->payload;
}
Exemplo n.º 14
0
bool
LSGmainSetPriorityPalmService(LSPalmService *psh, int priority, LSError *lserror)
{
    bool retVal;
    _LSErrorIfFail(psh != NULL, lserror);

    if (psh->public_sh)
    {
        retVal = LSGmainSetPriority(psh->public_sh, priority, lserror);
        if (!retVal) return false;
    }
    if (psh->private_sh)
    {
        retVal = LSGmainSetPriority(psh->private_sh, priority, lserror);
        if (!retVal) return false;
    }
    return true;
}
Exemplo n.º 15
0
/** 
 * @brief Checks if the message has subscription field with
 * subscribe=true
 * 
 * @param message
 * 
 * @retval true if has subscribe=true, false otherwise
 */
bool
LSMessageIsSubscription(LSMessage *message)
{
    bool ret = false;
    struct json_object *sub_object = NULL;
    const char *payload = LSMessageGetPayload(message);

    struct json_object *object = json_tokener_parse(payload);
    if (JSON_ERROR(object))
        goto exit;
   
    if (!json_object_object_get_ex(object, "subscribe", &sub_object) || JSON_ERROR(sub_object))
        goto exit;

    _LSErrorIfFail(json_object_get_type(sub_object) == json_type_boolean, NULL);
    
    ret = json_object_get_boolean(sub_object);

exit:
    if (!JSON_ERROR(object))
        json_object_put(object);
    return ret;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
/* 
 * This returns NULL or a ref'd message which you must unref when finished
 * with
 */
bool
LSFetchQueueWaitForMessage(LSFetchQueue *fq, LSMessage **ret_message,
                                 LSError *lserror)
{
    _LSErrorIfFail(fq != NULL, lserror);
    _LSErrorIfFail(ret_message != NULL, lserror);

    GSList *iter;
    //int nfd = -1;
    bool retVal;
    bool do_iteration = true;

    /* If we have already pending data we don't want to block on the iteration
     * since there may not be any more data coming */
    for (iter = fq->sh_list; iter != NULL; iter = iter->next)
    {
        LSHandle *sh = (LSHandle*)iter->data;
        
        if (_FetchMessageQueueSize(sh) > 0 || !LSCustomMessageQueueIsEmpty(sh->custom_message_queue))
        {
            do_iteration = false;
            break;
        }
    }

    /* 
     * 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
     */
    if (do_iteration)
    {
        g_main_context_iteration(fq->main_context, TRUE);
    }


    /**********
     * Dispatch
     **********/

    /* We treat the dispatch list like a circular list.  Stop when we see
     * the first message, or if we see the first element.
     *
     * This avoids starvation of any single connection.
     */
    if (!fq->dispatch_iter)
    {
        fq->dispatch_iter = fq->sh_list;
    }
    
    GSList *first = fq->dispatch_iter;
    LSMessage *message = NULL;

    while (fq->dispatch_iter != NULL)
    {
        LSHandle *sh = (LSHandle*)fq->dispatch_iter->data;

        //g_debug("%d Fetching message from %p %s", ++i, sh, sh->name);

        /* Fetch 1 message off incoming queue. */
        retVal = LSCustomFetchMessage(sh, &message, lserror);
        if (!retVal)
        {
            g_message("LSCustomFetchMessage returned false.");
            return false;
        }

        /* Get next connection. */
        fq->dispatch_iter = fq->dispatch_iter->next;
        if (!fq->dispatch_iter)
        {
            //g_message("dispatch iter end");
            fq->dispatch_iter = fq->sh_list;
        }

        if (fq->dispatch_iter == first)
        {
            //g_debug("Reached the first %p stopping...", first->data);
            fq->dispatch_iter = NULL;
        }
    
        /* Found a message! return it to user */
        if (message != NULL) break;
    }

    *ret_message = message;

    return true;
}