blob: b63587870ea548909ca23f48141773116545de9f [file] [log] [blame]
Radek Krejci3e6632f2021-03-22 22:08:21 +01001/**
2 * @file plugins.h
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Plugins manipulation.
5 *
6 * Copyright (c) 2021 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#ifndef LY_PLUGINS_H_
16#define LY_PLUGINS_H_
17
18#include "log.h"
19
stewegf7aeeae2024-04-02 13:15:52 +020020struct lyplg_ext_record;
21struct lyplg_type_record;
22
Radek Krejci3e6632f2021-03-22 22:08:21 +010023#ifdef __cplusplus
24extern "C" {
25#endif
26
27/**
Radek Krejci75104122021-04-01 15:37:45 +020028 * @page howtoPlugins Plugins
29 *
30 * libyang supports two types of plugins to better support generic features of YANG that need some specific code for
31 * their specific instances in YANG modules. This is the case of YANG types, which are derived from YANG built-in types.
32 * The description of a derived type can specify some additional requirements or restriction that cannot be implemented
33 * generically and some special code is needed. The second case for libyang plugins are YANG extensions. For YANG extensions,
34 * most of the specification is hidden in their description (e.g. allowed substatements or place of the extension
35 * instantiation) and libyang is not able to process such a text in a generic way.
36 *
37 * In both cases, libyang provides API to get functionality implementing the specifics of each type or extension.
38 * Furthermore, there are several internal plugins, implementing built-in data types and selected derived types and YANG
39 * extensions. These internal plugins uses the same API and can be taken as examples for implementing user plugins. Internal
40 * plugins are always loaded with the first created [context](@ref howtoContext) and unloaded with destroying the last one.
aPieceka8e855b2024-09-11 13:08:51 +020041 * The external plugins are in the same phase loaded as dynamic shared objects (shared libraries) from the default directories
42 * specified at compile time via cmake variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added
43 * for each plugin type) or separately via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default
44 * directories can be replaced runtime using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`.
45 * There is also a separate function ::lyplg_add() to manually add a plugin (dynamic shared object) anytime later.
46 * Another option to manually add an external plugin is using the ::lyplg_add_extension_plugin() or ::lyplg_add_type_plugin()
47 * which is useful when loading a dynamic shared object is problematic. These functions allow for setting the necessary callbacks
48 * for the plugin at runtime.
Radek Krejci75104122021-04-01 15:37:45 +020049 *
50 * Order of the plugins determines their priority. libyang searches for the first match with the extension and type, so the
51 * firstly loaded plugin for the specific item is used. Since the internal plugins are loaded always before the external
52 * plugins, the internal plugins cannot be replaced.
53 *
aPieceka8e855b2024-09-11 13:08:51 +020054 * Note, that manually added plugin via lyplg_add*() function is added with the lowest priority among other already loaded plugins.
55 * Also note that since all the plugins are unloaded with the destruction of the last context, creating a new context after that
56 * starts the standard plugins initiation and the manually added plugins are not loaded automatically.
Radek Krejci75104122021-04-01 15:37:45 +020057 *
58 * The following pages contain description of the API for creating user plugins.
59 *
60 * - @subpage howtoPluginsTypes
61 * - @subpage howtoPluginsExtensions
62 */
63
64/**
Radek Krejci3e6632f2021-03-22 22:08:21 +010065 * @defgroup plugins Plugins
66 * @{
67 *
68 */
69
70/**
71 * @brief Identifiers of the plugin type.
72 */
73enum LYPLG {
74 LYPLG_TYPE, /**< Specific type (typedef) */
75 LYPLG_EXTENSION /**< YANG extension */
76};
77
Radek Krejcibf940f92021-03-24 21:04:13 +010078/**
79 * @brief Manually load a plugin file.
80 *
81 * Note, that a plugin can be loaded only if there is at least one context. The loaded plugins are connected with the
82 * existence of a context. When all the contexts are destroyed, all the plugins are unloaded.
83 *
84 * @param[in] pathname Path to the plugin file. It can contain types or extensions plugins, both are accepted and correctly
85 * loaded.
86 *
87 * @return LY_SUCCESS if the file contains valid plugin compatible with the library version.
88 * @return LY_EDENIED in case there is no context and the plugin cannot be loaded.
89 * @return LY_EINVAL when pathname is NULL or the plugin contains invalid content for this libyang version.
90 * @return LY_ESYS when the plugin file cannot be loaded.
91 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010092LIBYANG_API_DECL LY_ERR lyplg_add(const char *pathname);
Radek Krejcibf940f92021-03-24 21:04:13 +010093
stewegf7aeeae2024-04-02 13:15:52 +020094/**
95 * @brief Manually load extension plugins from memory
96 *
97 * Note, that a plugin can be loaded only if there is at least one context. The loaded plugins are connected with the
98 * existence of a context. When all the contexts are destroyed, all the plugins are unloaded.
99 *
100 * @param[in] ctx The context to which the plugin should be associated with. If NULL, the plugin is considered to be shared
101 * between all existing contexts.
102 * @param[in] version The version of plugin records.
103 * @param[in] recs An array of plugin records provided by the plugin implementation. The array must be terminated by a zeroed
104 * record.
105 *
106 * @return LY_SUCCESS if the plugins with compatible version were successfully loaded.
107 * @return LY_EDENIED in case there is no context and the plugin cannot be loaded.
108 * @return LY_EINVAL when recs is NULL or the plugin contains invalid content for this libyang version.
109 */
110LIBYANG_API_DECL LY_ERR lyplg_add_extension_plugin(struct ly_ctx *ctx, uint32_t version, const struct lyplg_ext_record *recs);
111
112/**
113 * @brief Manually load type plugins from memory
114 *
115 * Note, that a plugin can be loaded only if there is at least one context. The loaded plugins are connected with the
116 * existence of a context. When all the contexts are destroyed, all the plugins are unloaded.
117 *
118 * @param[in] ctx The context to which the plugin should be associated with. If NULL, the plugin is considered to be shared
119 * between all existing contexts.
120 * @param[in] version The version of plugin records.
121 * @param[in] recs An array of plugin records provided by the plugin implementation. The array must be terminated by a zeroed
122 * record.
123 *
124 * @return LY_SUCCESS if the plugins with compatible version were successfully loaded.
125 * @return LY_EDENIED in case there is no context and the plugin cannot be loaded.
126 * @return LY_EINVAL when recs is NULL or the plugin contains invalid content for this libyang version.
127 */
128LIBYANG_API_DECL LY_ERR lyplg_add_type_plugin(struct ly_ctx *ctx, uint32_t version, const struct lyplg_type_record *recs);
Radek Krejci3e6632f2021-03-22 22:08:21 +0100129/** @} plugins */
130
131#ifdef __cplusplus
132}
133#endif
134
135#endif /* LY_PLUGINS_H_ */