Ejemplo n.º 1
0
/**
 * @brief Loads a plugin form provided filename.
 */
static int
sr_pd_load_plugin(sr_session_ctx_t *session, const char *plugin_filename, sr_pd_plugin_ctx_t *plugin_ctx)
{
    int rc = SR_ERR_OK;

    CHECK_NULL_ARG3(session, plugin_filename, plugin_ctx);

    plugin_ctx->filename = strdup(plugin_filename);
    CHECK_NULL_NOMEM_GOTO(plugin_ctx->filename, rc, cleanup);

    /* open the dynamic library with plugin */
    plugin_ctx->dl_handle = dlopen(plugin_filename, RTLD_LAZY);
    if (NULL == plugin_ctx->dl_handle) {
        SR_LOG_WRN("Unable to load the plugin: %s.", dlerror());
        rc = SR_ERR_INIT_FAILED;
        goto cleanup;
    }

    /* get init function pointer */
    *(void **) (&plugin_ctx->init_cb) = dlsym(plugin_ctx->dl_handle, SR_PLUGIN_INIT_FN_NAME);
    if (NULL == plugin_ctx->init_cb) {
        SR_LOG_WRN("Unable to find '%s' function: %s.", SR_PLUGIN_INIT_FN_NAME, dlerror());
        rc = SR_ERR_INIT_FAILED;
        goto cleanup;
    }

    /* get cleanup function pointer */
    *(void **) (&plugin_ctx->cleanup_cb) = dlsym(plugin_ctx->dl_handle, SR_PLUGIN_CLEANUP_FN_NAME);
    if (NULL == plugin_ctx->cleanup_cb) {
        SR_LOG_WRN("Unable to find '%s' function: %s.", SR_PLUGIN_CLEANUP_FN_NAME, dlerror());
        rc = SR_ERR_INIT_FAILED;
        goto cleanup;
    }

    /* get health check function pointer */
    *(void **) (&plugin_ctx->health_check_cb) = dlsym(plugin_ctx->dl_handle, SR_PLUGIN_HEALTH_CHECK_FN_NAME);
    if (NULL != plugin_ctx->health_check_cb) {
        SR_LOG_DBG("'%s' function found, health checks will be applied.", SR_PLUGIN_HEALTH_CHECK_FN_NAME);
    }

    return SR_ERR_OK;

cleanup:
    if (NULL != plugin_ctx->dl_handle) {
        dlclose(plugin_ctx->dl_handle);
    }
    free(plugin_ctx->filename);
    return rc;
}
Ejemplo n.º 2
0
/**
 * @brief Removes a session from the session list of the connection.
 */
static void
cl_conn_remove_session(sr_conn_ctx_t *connection, sr_session_ctx_t *session)
{
    sr_session_list_t *tmp = NULL, *prev = NULL;

    CHECK_NULL_ARG_VOID2(connection, session);

    pthread_mutex_lock(&connection->lock);

    /* find matching session in linked list */
    tmp = connection->session_list;
    while ((NULL != tmp) && (tmp->session != session)) {
        prev = tmp;
        tmp = tmp->next;
    }

    /* remove the session from linked-list */
    if (NULL != tmp) {
        if (NULL != prev) {
            /* tmp is NOT the first item in list - skip it */
            prev->next = tmp->next;
        } else if (NULL != tmp->next) {
            /* tmp is the first, but not last item in list - skip it */
            connection->session_list = tmp->next;
        } else {
            /* tmp is the only item in the list */
            connection->session_list = NULL;
        }
        free(tmp);
    } else {
        SR_LOG_WRN("Session %p not found in session list of connection.", (void*)session);
    }

    pthread_mutex_unlock(&connection->lock);
}
Ejemplo n.º 3
0
/**
 * @brief Logging callback called from libyang for each log entry.
 */
static void
srcfg_ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path)
{
    switch (level) {
        case LY_LLERR:
            if (ly_diminish_errors)
                SR_LOG_WRN("libyang: %s", msg);
            else
                SR_LOG_ERR("libyang: %s", msg);
            break;
        case LY_LLWRN:
            SR_LOG_WRN("libyang: %s", msg);
            break;
        case LY_LLVRB:
            SR_LOG_INF("libyang: %s", msg);
            break;
        case LY_LLDBG:
            SR_LOG_DBG("libyang: %s", msg);
            break;
        default:
            break;
    }
}
Ejemplo n.º 4
0
int
cl_request_process(sr_session_ctx_t *session, Sr__Msg *msg_req, Sr__Msg **msg_resp,
        sr_mem_ctx_t *sr_mem_resp, const Sr__Operation expected_response_op)
{
    int rc = SR_ERR_OK;
    struct timeval tv = { 0, };

    CHECK_NULL_ARG4(session, session->conn_ctx, msg_req, msg_resp);

    SR_LOG_DBG("Sending %s request.", sr_gpb_operation_name(expected_response_op));

    pthread_mutex_lock(&session->conn_ctx->lock);
    /* some operation may take more time, raise the timeout */
    if (SR__OPERATION__COMMIT == expected_response_op || SR__OPERATION__COPY_CONFIG == expected_response_op ||
            SR__OPERATION__RPC == expected_response_op || SR__OPERATION__ACTION == expected_response_op) {
        tv.tv_sec = SR_LONG_REQUEST_TIMEOUT;
        tv.tv_usec = 0;
        rc = setsockopt(session->conn_ctx->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
        if (-1 == rc) {
            SR_LOG_WRN("Unable to set timeout for socket operations: %s", sr_strerror_safe(errno));
        }
    }

    /* send the request */
    rc = cl_message_send(session->conn_ctx, msg_req);
    if (SR_ERR_OK != rc) {
        SR_LOG_ERR("Unable to send the message with request (session id=%"PRIu32", operation=%s).",
                session->id, sr_gpb_operation_name(msg_req->request->operation));
        pthread_mutex_unlock(&session->conn_ctx->lock);
        return rc;
    }

    SR_LOG_DBG("%s request sent, waiting for response.", sr_gpb_operation_name(expected_response_op));

    /* receive the response */
    rc = cl_message_recv(session->conn_ctx, msg_resp, sr_mem_resp);
    if (SR_ERR_OK != rc) {
        SR_LOG_ERR("Unable to receive the message with response (session id=%"PRIu32", operation=%s).",
                session->id, sr_gpb_operation_name(msg_req->request->operation));
        pthread_mutex_unlock(&session->conn_ctx->lock);
        return rc;
    }

    /* change socket timeout to the standard value */
    if (SR__OPERATION__COMMIT == expected_response_op || SR__OPERATION__COPY_CONFIG == expected_response_op ||
            SR__OPERATION__RPC == expected_response_op || SR__OPERATION__ACTION == expected_response_op) {
        tv.tv_sec = SR_REQUEST_TIMEOUT;
        rc = setsockopt(session->conn_ctx->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
        if (-1 == rc) {
            SR_LOG_WRN("Unable to set timeout for socket operations: %s", sr_strerror_safe(errno));
        }
    }

    pthread_mutex_unlock(&session->conn_ctx->lock);

    SR_LOG_DBG("%s response received, processing.", sr_gpb_operation_name(expected_response_op));

    /* validate the response */
    rc = sr_gpb_msg_validate(*msg_resp, SR__MSG__MSG_TYPE__RESPONSE, expected_response_op);
    if (SR_ERR_OK != rc) {
        SR_LOG_ERR("Malformed message with response received (session id=%"PRIu32", operation=%s).",
                session->id, sr_gpb_operation_name(msg_req->request->operation));
        return rc;
    }

    /* check for errors */
    if (SR_ERR_OK != (*msg_resp)->response->result) {
        if (NULL != (*msg_resp)->response->error) {
            /* set detailed error information into session */
            rc = cl_session_set_error(session, (*msg_resp)->response->error->message, (*msg_resp)->response->error->xpath);
        }
        /* log the error (except expected ones) */
        if (SR_ERR_NOT_FOUND != (*msg_resp)->response->result &&
                SR_ERR_VALIDATION_FAILED != (*msg_resp)->response->result &&
                SR_ERR_UNAUTHORIZED != (*msg_resp)->response->result &&
                SR_ERR_OPERATION_FAILED != (*msg_resp)->response->result) {
            SR_LOG_ERR("Error by processing of the %s request (session id=%"PRIu32"): %s.",
                    sr_gpb_operation_name(msg_req->request->operation), session->id,
                (NULL != (*msg_resp)->response->error && NULL != (*msg_resp)->response->error->message) ?
                        (*msg_resp)->response->error->message : sr_strerror((*msg_resp)->response->result));
        }
        return (*msg_resp)->response->result;
    }

    return rc;
}
Ejemplo n.º 5
0
/**
 * @brief Loads all plugins in plugins directory.
 */
static int
sr_pd_load_plugins(sr_pd_ctx_t *ctx)
{
    DIR *dir;
    struct dirent entry, *result;
    char *env_str = NULL;
    char plugins_dir[PATH_MAX - 256] = { 0, };
    char plugin_filename[PATH_MAX + 1] = { 0, };
    sr_pd_plugin_ctx_t *tmp = NULL;
    bool init_retry_needed = false;
    int ret = 0;
    int rc = SR_ERR_OK;

    CHECK_NULL_ARG(ctx);

    /* get plugins dir from environment variable, or use default one */
    env_str = getenv("SR_PLUGINS_DIR");
    if (NULL != env_str) {
        strncat(plugins_dir, env_str, PATH_MAX - 257);
    } else {
        strncat(plugins_dir, SR_PLUGINS_DIR, PATH_MAX - 257);
    }

    SR_LOG_DBG("Loading plugins from '%s'.", plugins_dir);

    dir = opendir(plugins_dir);
    if (NULL == dir) {
        SR_LOG_ERR("Error by opening plugin directory: %s.", sr_strerror_safe(errno));
        return SR_ERR_INVAL_ARG;
    }
    do {
        ret = readdir_r(dir, &entry, &result);
        if (0 != ret) {
            SR_LOG_ERR("Error by reading plugin directory: %s.", sr_strerror_safe(errno));
            break;
        }
        if ((NULL != result) && (DT_DIR != entry.d_type)
                && (0 != strcmp(entry.d_name, ".")) && (0 != strcmp(entry.d_name, ".."))) {
            SR_LOG_DBG("Loading plugin from file '%s'.", entry.d_name);
            snprintf(plugin_filename, PATH_MAX, "%s/%s", plugins_dir, entry.d_name);

            /* realloc plugins array */
            tmp = realloc(ctx->plugins, sizeof(*ctx->plugins) * (ctx->plugins_cnt + 1));
            if (NULL == tmp) {
                SR_LOG_ERR_MSG("Unable to realloc plugins array, skipping the rest of plugins.");
                break;
            }
            ctx->plugins = tmp;

            /* load the plugin */
            rc = sr_pd_load_plugin(ctx->session, plugin_filename, &(ctx->plugins[ctx->plugins_cnt]));
            if (SR_ERR_OK != rc) {
                SR_LOG_WRN("Ignoring the file '%s'.", plugin_filename);
                continue;
            }

            /* initialize the plugin */
            rc = sr_pd_init_plugin(ctx->session, &(ctx->plugins[ctx->plugins_cnt]));
            if (SR_ERR_OK != rc) {
                init_retry_needed = true;
            }
            ctx->plugins_cnt += 1;
        }
    } while (NULL != result);
    closedir(dir);

    if (init_retry_needed) {
        SR_LOG_DBG("Scheduling plugin init retry after %d seconds.", SR_PLUGIN_INIT_RETRY_TIMEOUT);
        ev_timer_start(ctx->event_loop, &ctx->init_retry_timer);
    }

    return SR_ERR_OK;
}