/**
 *******************************************************************************
 * @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 Increment ref count on message object.  You MUST call this if you wish to store
*        LSMessage yourself.  A LSMessageRef() MUST be paired with a LSMessageUnref()
*        lest you leak memory.
* 
* @param  message 
*/
void
LSMessageRef(LSMessage *message)
{
    LS_ASSERT(message != NULL);
    LS_ASSERT(g_atomic_int_get (&message->ref) > 0); 

    //g_debug("%s(%p)", __FUNCTION__, message);

    g_atomic_int_inc(&message->ref);
}
/** 
 *******************************************************************************
 * @brief Increment the ref count of a client.
 * 
 * @param  client   IN  client 
 *******************************************************************************
 */
void
_LSTransportClientRef(_LSTransportClient *client)
{
    LS_ASSERT(client != NULL);
    LS_ASSERT(g_atomic_int_get(&client->ref) > 0);

    g_atomic_int_inc(&client->ref);

    _ls_verbose("%s: %d (%p)\n", __func__, client->ref, client);
}
/**
 *******************************************************************************
 * @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;
}
/** 
* @brief Decrement ref count on message object.  Object is freed if ref goes to zero.
* 
* @param  message 
*/
void
LSMessageUnref(LSMessage *message)
{
    LS_ASSERT(message != NULL);
    LS_ASSERT(g_atomic_int_get (&message->ref) > 0); 

    //g_debug("%s(%p)", __FUNCTION__, message);

    if (g_atomic_int_dec_and_test(&message->ref))
    {
        _LSMessageFree(message);
    }
}
/** 
 *******************************************************************************
 * @brief Free an incoming queue.
 * 
 * @param  incoming IN incoming 
 *******************************************************************************
 */
void _LSTransportIncomingFree(_LSTransportIncoming *incoming)
{
    LS_ASSERT(incoming != NULL);

    /* want to have processed all incoming messages so we don't lose any */
    LS_ASSERT(incoming->tmp_msg == NULL);
    LS_ASSERT(g_queue_is_empty(incoming->complete_messages));
    g_queue_free(incoming->complete_messages);

#ifdef MEMCHECK
    memset(incoming, 0xFF, sizeof(_LSTransportIncoming));
#endif

    g_slice_free(_LSTransportIncoming, incoming);
}
Beispiel #7
0
/*-------------------------------------
    Determine if *this Buffer Object is currently active.
-------------------------------------*/
bool BufferObject::is_bound() const noexcept {
    GLint typeToCheck = 0;

    switch (get_type()) {
        case buffer_use_t::VBO_BUFFER_ARRAY:
            typeToCheck = GL_ARRAY_BUFFER_BINDING;
            break;

        case buffer_use_t::VBO_BUFFER_ELEMENT:
            typeToCheck = GL_ELEMENT_ARRAY_BUFFER_BINDING;
            break;

        case buffer_use_t::VBO_BUFFER_TRANSFORM_FEEDBACK:
            typeToCheck = GL_TRANSFORM_FEEDBACK_BUFFER_BINDING;
            break;

        case buffer_use_t::VBO_BUFFER_UNIFORM_BUFFER:
            typeToCheck = GL_UNIFORM_BUFFER_BINDING;
            break;

        default:
            LS_LOG_ERR("Forgot to implement an enumeration for the current buffer type!");
            break;
    }

    // just fail, no room for debug statements here.
    LS_ASSERT(typeToCheck != 0);

    GLint currentBuffer = 0;
    glGetIntegerv(typeToCheck, &currentBuffer);
    return currentBuffer == (GLint)this->gpuId;
}
Beispiel #8
0
inline void
_lshandle_validate(LSHandle *sh)
{
    if (sh && sh->history.magic_state_num != LSHANDLE_MAGIC_STATE_VALID)
    {
        Dl_info create_info;
        Dl_info destroy_info;
        bool create_info_valid = false;
        bool destroy_info_valid = false;

        if (sh->history.creator_ret_addr)
        {
            create_info_valid = dladdr(sh->history.creator_ret_addr, &create_info);
        }

        if (sh->history.destroyer_ret_addr)
        {
            destroy_info_valid = dladdr(sh->history.destroyer_ret_addr, &destroy_info);
        }

        LOG_LS_ERROR(MSGID_LS_INVALID_HANDLE, 5,
                     PMLOGKFV("HANDLER", "%p", sh),
                     PMLOGKS("CREATE_DLI_FNAME", create_info_valid ? create_info.dli_fname : "(unknown)"),
                     PMLOGKS("CREATE_DLI_SNAME", create_info_valid ? create_info.dli_sname : "(unknown)"),
                     PMLOGKS("DESTR_DLI_FNAME", destroy_info_valid ? destroy_info.dli_fname : "(unknown)"),
                     PMLOGKS("DESTR_DLI_SNAME", destroy_info_valid ? destroy_info.dli_sname : "(unknown)"),
                     "%s: Invalid handle", __func__);
        LS_ASSERT(!"Invalid LSHandle");
    }
}
/** 
 *******************************************************************************
 * @brief Decrement the ref count of a client.
 * 
 * @param  client   IN  client 
 *******************************************************************************
 */
void
_LSTransportClientUnref(_LSTransportClient *client)
{
    LS_ASSERT(client != NULL);
    LS_ASSERT(g_atomic_int_get(&client->ref) > 0);

    if (g_atomic_int_dec_and_test(&client->ref))
    {
        _ls_verbose("%s: %d (%p)\n", __func__, client->ref, client);
        _LSTransportClientFree(client);
    }
    else
    {
        _ls_verbose("%s: %d (%p)\n", __func__, client->ref, client);
    }
}
Beispiel #10
0
inline void
_lshandle_validate(LSHandle *sh)
{
    if (sh && sh->history.magic_state_num != LSHANDLE_MAGIC_STATE_VALID)
    {
        Dl_info create_info;
        Dl_info destroy_info;
        bool create_info_valid = false;
        bool destroy_info_valid = false;

        if (sh->history.creator_ret_addr)
        {
            create_info_valid = dladdr(sh->history.creator_ret_addr, &create_info);
        }

        if (sh->history.destroyer_ret_addr)
        {
            destroy_info_valid = dladdr(sh->history.destroyer_ret_addr, &destroy_info);
        }

        g_critical("%s: Invalid handle %p, created by call from %s:%s, destroyed by call from %s:%s", __func__,
            sh,
            create_info_valid ? create_info.dli_fname : "(unknown)",
            create_info_valid ? create_info.dli_sname : "(unknown)",
            destroy_info_valid ? destroy_info.dli_fname : "(unknown)",
            destroy_info_valid ? destroy_info.dli_sname : "(unknown)"
        );
        LS_ASSERT(!"invalid LSHandle");
    }
}
/**
 *******************************************************************************
 * @brief Get the unique name from a "ServiceStatus" message.
 *
 * @param  message  IN  message
 *
 * @retval  name string on success
 * @retval  NULL on failure
 *******************************************************************************
 */
const char*
LSTransportServiceStatusSignalGetUniqueName(_LSTransportMessage *message)
{
    /* TODO: we may want this eventually, it's pretty much the same as GetServiceName */
    LOG_LS_ERROR(MSGID_LS_NOT_IMPLEMENTED, 0, "Not yet implemented!");
    LS_ASSERT(0);
    return NULL;
}
Beispiel #12
0
static void
_FreeMonitorListInfoItem(_LSMonitorListInfo *info)
{
    LS_ASSERT(info != NULL);
    g_free(info->unique_name);
    g_free(info->service_name);
    g_free(info->exe_path);
    g_free(info->service_type);
    g_free(info);
}
/**
 *******************************************************************************
 * @brief Free a serial map entry.
 *
 * @param  entry    IN  entry
 *******************************************************************************
 */
void
_LSTransportSerialMapEntryFree(_LSTransportSerialMapEntry *entry)
{
    LS_ASSERT(entry != NULL);

#ifdef MEMCHECK
    memset(entry, 0xFF, sizeof(_LSTransportSerialMapEntry));
#endif

    g_slice_free(_LSTransportSerialMapEntry, entry);
}
Beispiel #14
0
void _LSCatalogRemoveClientSubscriptions(_Catalog *catalog, _LSTransportClient *client)
{
    LS_ASSERT(catalog != NULL);
    LS_ASSERT(_LSTransportClientGetUniqueName(client) != NULL);

    const char *client_name = _LSTransportClientGetUniqueName(client);

    _CatalogLock(catalog);

    char *key = NULL;
    _SubList *tokens = NULL;
    if (!g_hash_table_lookup_extended(catalog->client_subscriptions, client_name,
                                      (gpointer *) &key, (gpointer *) &tokens))
    {
        LOG_LS_DEBUG("Disconnected service had no subscriptions: %s", client->service_name);
        _CatalogUnlock(catalog);
        return;
    }

    g_hash_table_steal(catalog->client_subscriptions, client_name);
    g_free(key);

    _CatalogUnlock(catalog);

    int i;
    for (i = _SubListLen(tokens) - 1; i >= 0; --i)
    {
        const char *token = _SubListGet(tokens, i);

        _Subscription *subs = _SubscriptionAcquire(catalog, token);
        if (subs)
        {
            _CatalogRemoveToken(catalog, token, true);
            _SubscriptionRelease(catalog, subs);
        }
    }

    _SubListFree(tokens);
}
Beispiel #15
0
static void
_SubscriptionRelease(_Catalog *catalog, _Subscription *subs)
{
    if (subs)
    {
        LS_ASSERT(g_atomic_int_get(&subs->ref) > 0);

        if (g_atomic_int_dec_and_test(&subs->ref))
        {
            _SubscriptionFree(catalog, subs);
        }
    }
}
/**
 *******************************************************************************
 * @brief Free an outgoing queue.
 *
 * @param  outgoing     IN  outgoing queue
 *******************************************************************************
 */
void
_LSTransportOutgoingFree(_LSTransportOutgoing *outgoing)
{
    LS_ASSERT(outgoing != NULL);
    LS_ASSERT(outgoing->queue != NULL);
    LS_ASSERT(outgoing->serial != NULL);

    while (!g_queue_is_empty(outgoing->queue))
    {
        _LSTransportMessage *message = g_queue_pop_head(outgoing->queue);
        _LSTransportMessageUnref(message);
    }
    g_queue_free(outgoing->queue);

    _LSTransportSerialFree(outgoing->serial);

#ifdef MEMCHECK
    memset(outgoing, 0xFF, sizeof(_LSTransportOutgoing));
#endif

    g_slice_free(_LSTransportOutgoing, outgoing);
}
/**
 *******************************************************************************
 * @brief Free a serial list item.
 *
 * @param  list_item    IN serial list item to free
 *******************************************************************************
 */
void
_LSTransportSerialListItemFree(_LSTransportSerialListItem *list_item)
{
    LS_ASSERT(list_item != NULL);

    _LSTransportMessageUnref(list_item->message);

#ifdef MEMCHECK
    memset(list_item, 0xFF, sizeof(_LSTransportSerialListItem));
#endif

    g_slice_free(_LSTransportSerialListItem, list_item);
}
/** 
 *******************************************************************************
 * @brief Free a credentials object.
 * 
 * @param  cred     IN  credentials
 *******************************************************************************
 */
void
_LSTransportCredFree(_LSTransportCred *cred)
{
    LS_ASSERT(cred != NULL);
    g_free((char*)cred->exe_path);
    g_free((char*)cred->cmd_line);

#ifdef MEMCHECK
    memset(cred, 0xFF, sizeof(_LSTransportCred));
#endif

    g_slice_free(_LSTransportCred, cred);
}
/** 
 *******************************************************************************
 * @brief Get the credentials from a unix domain socket.
 * 
 * @param  fd           IN       unix domain socket fd 
 * @param  cred         IN/OUT   credentials
 * @param  lserror      OUT      set on error 
 * 
 * @retval  true on success
 * @retval  false on failure
 *******************************************************************************
 */
bool
_LSTransportGetCredentials(int fd, _LSTransportCred *cred, LSError *lserror)
{
    LS_ASSERT(cred != NULL);

#ifdef SO_PEERCRED
    struct ucred tmp_cred;

    socklen_t len = sizeof(tmp_cred);

    if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &tmp_cred, &len) != 0)
    {
        _LSErrorSetFromErrno(lserror, errno);
        return false;        
    }

    cred->pid = tmp_cred.pid;
    cred->uid = tmp_cred.uid;
    cred->gid = tmp_cred.gid;

    /* NOV-101642: Only do the following check if we're the hub */
    if (_LSTransportIsHub())
    {
        if (tmp_cred.pid != LS_PID_INVALID)
        {
            cred->exe_path = _LSTransportPidToExe(tmp_cred.pid, lserror);

            if (!cred->exe_path)
            {
                return false;
            }

            cred->cmd_line = _LSTransportPidToCmdLine(tmp_cred.pid, lserror);

            if (!cred->cmd_line)
            {
                g_free((char*)cred->exe_path);
                cred->exe_path = NULL;
                return false;
            }
        }
    }

#else
    cred->pid = LS_PID_INVALID;
    cred->uid = LS_UID_INVALID;
    cred->gid = LS_GID_INVALID;
#endif
    
    return true;
}
/**
 *******************************************************************************
 * @brief Save a serial (token) in the queue and map.
 *
 * @attention locks the serial lock
 *
 * @param  serial_info  IN  serial info
 * @param  serial       IN  message serial (token) to save
 * @param  lserror      OUT set on error
 *
 * @retval  true on success
 * @retval  false on failure
 *******************************************************************************
 */
bool
_LSTransportSerialSave(_LSTransportSerial *serial_info, _LSTransportMessage *message, LSError *lserror)
{
    LSMessageToken serial = _LSTransportMessageGetToken(message);
    _LSTransportSerialListItem *item = _LSTransportSerialListItemNew(serial, message);

    SERIAL_INFO_LOCK(&serial_info->lock);

    g_queue_push_tail(serial_info->queue, item);
    GList *list = g_queue_peek_tail_link(serial_info->queue);

    LS_ASSERT(list != NULL);

    _LSTransportSerialMapEntry *map_entry = _LSTransportSerialMapEntryNew(serial, list);

    LS_ASSERT(NULL == g_hash_table_lookup(serial_info->map, &map_entry->serial));

    g_hash_table_insert(serial_info->map, &map_entry->serial, map_entry);

    SERIAL_INFO_UNLOCK(&serial_info->lock);

    return true;
}
/**
 *******************************************************************************
 * @brief Send a signal.
 *
 * @param  transport    IN  transport
 * @param  category     IN  category
 * @param  method       IN  method (optional, NULL means none)
 * @param  payload      IN  payload
 * @param  lserror      OUT set on error
 *
 * @retval  true on success
 * @retval  false on failure
 *******************************************************************************
 */
bool
LSTransportSendSignal(_LSTransport *transport, const char *category, const char *method, const char *payload, LSError *lserror)
{
    bool ret = true;

    _LSTransportMessage *message = LSTransportMessageSignalNewRef(category, method, payload);

    LS_ASSERT(transport->hub != NULL);

    ret = _LSTransportSendMessage(message, transport->hub, NULL, lserror);

    _LSTransportMessageUnref(message);

    return ret;
}
Beispiel #22
0
const char *
_SubListGet(_SubList *tokens, int i)
{
    if (i < 0 || i >= tokens->len)
    {
        LOG_LS_ERROR(MSGID_LS_SUBSCRIPTION_ERR, 0,
                     "%s: attempting to get out of range subscription %d\n"
                     "It is possible you forgot to follow the pattern: "
                     " LSSubscriptionHasNext() + LSSubscriptionNext()",
                     __FUNCTION__, i);
        return NULL;
    }

    LS_ASSERT(i >= 0 && i < tokens->len);
    return g_ptr_array_index(tokens, i);
}
/** 
 *******************************************************************************
 * @brief Allocate a new incoming queue.
 * 
 * @retval  incoming queue on success
 * @retval  NULL on failure
 *******************************************************************************
 */
_LSTransportIncoming* _LSTransportIncomingNew(void)
{
    _LSTransportIncoming *incoming = g_slice_new0(_LSTransportIncoming);

    if (incoming)
    {
        /* This cannot fail when using eglibc (2.15) */
        if (pthread_mutex_init(&incoming->lock, NULL)) {
            g_slice_free(_LSTransportIncoming, incoming);
            return NULL;
        }
        incoming->complete_messages = g_queue_new();
        LS_ASSERT(incoming->complete_messages != NULL);
    }
    return incoming;
}
Beispiel #24
0
static _Subscription *
_SubscriptionAcquire(_Catalog *catalog, const char *uniqueToken)
{
    _CatalogLock(catalog);

    _Subscription *subs=
        g_hash_table_lookup(catalog->token_map, uniqueToken);
    if (subs)
    {
        LS_ASSERT(g_atomic_int_get(&subs->ref) > 0);
        g_atomic_int_inc(&subs->ref);
    }

    _CatalogUnlock(catalog);

    return subs;
}
Beispiel #25
0
static void
_CatalogCallCancelNotifications(_Catalog *catalog, const char *uniqueToken)
{
    LS_ASSERT(uniqueToken);
    _CatalogLock(catalog);
    if (catalog->cancel_notify_list)
    {
        int idx;
        for (idx = 0; idx < catalog->cancel_notify_list->len; ++idx)
        {
            _SubscriberCancelNotification *scn = g_ptr_array_index(catalog->cancel_notify_list, idx);
            if (scn->function)
            {
                scn->function(catalog->sh, uniqueToken, scn->context);
            }
        }
    }
    _CatalogUnlock(catalog);
}
/**
 *******************************************************************************
 * @brief Get the service name from a "ServceStatus" message. The name is
 * allocated and should be freed.
 *
 * @param  message  IN  message
 *
 * @retval name string on success
 * @retval NULL on error
 *******************************************************************************
 */
char*
LSTransportServiceStatusSignalGetServiceName(_LSTransportMessage *message)
{
    JSchemaInfo schemaInfo;
    jschema_info_init(&schemaInfo, jschema_all(), NULL, NULL);

    LS_ASSERT(_LSTransportMessageGetType(message) == _LSTransportMessageTypeServiceDownSignal
              || _LSTransportMessageGetType(message) == _LSTransportMessageTypeServiceUpSignal);

    char *service_name = NULL;
    jvalue_ref service_name_obj = NULL;
    const char *payload = _LSTransportMessageGetPayload(message);

    if (!payload)
    {
        LOG_LS_ERROR(MSGID_LS_INVALID_JSON, 0, "Unable to get payload from message");
        return NULL;
    }

    /* get the serviceName part of the JSON object */
    jvalue_ref payload_json = jdom_parse(j_cstr_to_buffer(payload),
                                         DOMOPT_NOOPT, &schemaInfo);

    bool ret = jobject_get_exists(payload_json,
                                  J_CSTR_TO_BUF(SERVICE_STATUS_SERVICE_NAME),
                                  &service_name_obj);

    if (ret)
    {
        raw_buffer service_name_buf = jstring_get_fast(service_name_obj);
        service_name = g_strndup(service_name_buf.m_str, service_name_buf.m_len);
    }
    else
    {
        LOG_LS_ERROR(MSGID_LS_INVALID_JSON, 0, "Unable to get service name string from payload: %s", payload);
    }

    j_release(&payload_json);

    return service_name;
}
_LSTransportMonitorSerial
_LSTransportShmGetSerial(_LSTransportShm* shm)
{
    LS_ASSERT(shm != NULL);

    _LSTransportMonitorSerial ret = MONITOR_SERIAL_INVALID;

    /* Make sure a rogue process didn't mess with the shared mem */
    if (shm->data->front_fence == FENCE_VAL &&
        shm->data->back_fence == FENCE_VAL)
    {
        pthread_mutex_lock(&shm->data->lock);
        ret = ++shm->data->serial;

        if (unlikely(ret == MONITOR_SERIAL_INVALID))
        {
            ret++;
        }
        pthread_mutex_unlock(&shm->data->lock);
    }

    return ret;
}
/**
 *******************************************************************************
 * @brief Free transport serial info
 *
 * @param  serial_info  IN  serial info
 *******************************************************************************
 */
void
_LSTransportSerialFree(_LSTransportSerial *serial_info)
{
    LS_ASSERT(serial_info != NULL);

    SERIAL_INFO_LOCK(&serial_info->lock);

    while (!g_queue_is_empty(serial_info->queue))
    {
         _LSTransportSerialListItem *item = g_queue_pop_head(serial_info->queue);
        _LSTransportSerialListItemFree(item);
    }

    g_queue_free(serial_info->queue);
    g_hash_table_destroy(serial_info->map); /* key and value destroy functions clean this up */

    SERIAL_INFO_UNLOCK(&serial_info->lock);

#ifdef MEMCHECK
    memset(serial_info, 0xFF, sizeof(_LSTransportSerial));
#endif

    g_slice_free(_LSTransportSerial, serial_info);
}
/** 
 *******************************************************************************
 * @brief Get the process' command line.
 * 
 * @param  cred     IN  credentials 
 * 
 * @retval  cmdline on success
 * @retval  NULL on failure
 *******************************************************************************
 */
inline const char*
_LSTransportCredGetCmdLine(const _LSTransportCred *cred)
{
    LS_ASSERT(cred != NULL);
    return cred->cmd_line;
}
/** 
 *******************************************************************************
 * @brief Get the full path to executable.
 * 
 * @param  cred     IN  credentials 
 * 
 * @retval  path on success
 * @retval  NULL on failure
 *******************************************************************************
 */
inline const char*
_LSTransportCredGetExePath(const _LSTransportCred *cred)
{
    LS_ASSERT(cred != NULL);
    return cred->exe_path;
}