| Both sides previous revision Previous revision Next revision | Previous revision |
| docs:techref:rpcd [2018/10/24 19:57] – [plugin executables] stokito | docs:techref:rpcd [2023/10/14 06:08] (current) – update vgaetera |
|---|
| ====== rpcd (OpenWrt ubus RPC backend server) ====== | ====== rpcd: OpenWrt ubus RPC daemon for backend server ====== |
| | In OpenWrt we commonly use [[docs:techref:ubus|ubus]] for all kinds of communication. It can provide info from various software as well as request various actions. Nevertheless, not every part of OpenWrt has a daemon that can register itself using ''ubus''. For an example ''uci'' and ''opkg'' are command-line tools without any background process running all the time. |
| |
| The code is published under ISC and can be found via git at [[git://git.openwrt.org/project/rpcd.git]] or via http at [[http://git.openwrt.org/?p=project/rpcd.git;a=summary]]. It's included in OpenWrt since r37877. | It would be not efficient to write a daemon for every software like this and run them independently. This is why ''rpcd'' was developed. It’s a tiny daemon with support for plugins using trivial API. It loads library ''%%.so%%'' files and calls init function of each of them. |
| |
| ===== plugin executables ===== | The code is published under [[wp>ISC_license|ISC license]] and can be found via git at [[https://git.openwrt.org/project/rpcd.git]]. |
| |
| It is possible to expose shell script functionality over ubus by using rpcd plugin executables functionality. Executables stored in ///usr/libexec/rpcd/// directory will be runned by rpcd. Lets look at the following example: | ==== Default plugins ==== |
| | There are few small plugins distributed with the ''rpcd'' sources. Two of them (''session'' and ''uci'') are built-in, others are optional and have to be build as separated ''%%.so%%'' libraries. Apart from that there are other projects providing their own plugins. |
| | |
| | ===== plugin executables ===== |
| | It is possible to expose shell script functionality over ubus by using ''rpcd'' plugin executables functionality. Executables stored in ''/usr/libexec/rpcd/'' directory will be run by ''rpcd''. Lets look at the following example: |
| |
| <code> | <code bash> |
| $ cat << EOF > /usr/libexec/rpcd/foo | mkdir -p /usr/libexec/rpcd |
| | cat << "EOF" > /usr/libexec/rpcd/foo |
| #!/bin/sh | #!/bin/sh |
| |
| esac | esac |
| EOF | EOF |
| $ chmod +x /usr/libexec/rpcd/foo | chmod +x /usr/libexec/rpcd/foo |
| | service rpcd restart |
| </code> | </code> |
| |
| This will create new ubus functions which then can be used (after restarting rpcd): | This will create new ubus functions which then can be used (after restarting rpcd): |
| |
| <code> | <code bash> |
| $ ubus -v list | $ ubus -v list foo |
| ... | 'foo' @a9482c5b |
| 'foo' @686f0592 | |
| "bar":{"arg1":"Boolean","arg2":"Integer","arg3":"String"} | "bar":{"arg1":"Boolean","arg2":"Integer","arg3":"String"} |
| "toto":{} | "toto":{} |
| ... | "failme":{} |
| $ ubus call -S foo bar '{"arg1": true }' | |
| | $ ubus -S call foo bar '{"arg1": true }' |
| {{"hello":"world"}} | {{"hello":"world"}} |
| | |
| $ ubus -S call foo toto | $ ubus -S call foo toto |
| {"something":"somevalue"} | {"something":"somevalue"} |
| # ubus -S call foo failme | |
| # echo $? | $ ubus -S call foo failme |
| | |
| | $ echo $? |
| 2 | 2 |
| </code> | </code> |
| |
| On startup rpcd will call all executables in ///usr/libexec/rpcd/// with //argv[1]// set to "list". For a plugin, which responds with a valid list of methods and signatures, ubus method with appropriate arguments will be created. When a method provided by the plugin is about to be invoked, rpcd calls the binary with //argv[1]// set to "call" and //argv[2]// set to the invoked method name. **The actual data is then sent by the ubus client via stdin.** Ie, If you're testing the script itself, you need to use ''echo '{"arg1": 42}' | yourscript call yourmethod''. You //cannot// simply use ''yourscript call yourmethod '{"arg1": 42}''' as you might have expected. | On startup rpcd will call all executables in ''/usr/libexec/rpcd/'' with ''argv[1]'' set to "list". For a plugin, which responds with a valid list of methods and signatures, ubus method with appropriate arguments will be created. When a method provided by the plugin is about to be invoked, ''rpcd'' calls the binary with ''argv[1]'' set to ''call'' and ''argv[2]'' set to the invoked method name. |
| | |
| | **The actual data is then sent by the ''ubus'' client via ''stdin''.** I.e. if you're testing the script itself, you need to use |
| | |
| | <code bash> |
| | echo '{"arg1": 42}' | yourscript call yourmethod |
| | </code> |
| | |
| | You //cannot// simply use ''yourscript call yourmethod '{"arg1": 42}''' as you might have expected. |
| | |
| | The method signature is a simple object containing ''key:value'' pairs. The argument type is inferred from the value. If the value is a string (regardless of the contents) it is registered as string, if the value is a bool true or false, its registered as bool, if the value is an integer, it is registered as either int8, int16, int32 or int64 depending on the value i.e. ''"foo": 16'' will be ''INT16'', ''"foo": 64'' will be ''INT64'', ''"foo": 8'' will be ''INT8'' and everything else will be ''INT32''. |
| |
| The method signature is a simple object containing //key//://value// pairs. The argument type is inferred from the value. If the value is a string (regardless of the contents) it is registered as string, if the value is a bool true or false, its registered as bool, if the value is an integer, it is registered as either int8, int16, int32 or int64 depending on the value ("foo": 16 will be INT16, "foo": 64 will be INT64, "foo": 8 will be INT8 and everything else will be INT32). | It is enough to issue ''service rpcd reload'' to make it pick up new plugin executables, that way one does not lose active sessions. |
| |
| It is enough to issue '/etc/init.d/rpcd reload' to make it pick up new plugin executables, that way one does not lose active sessions. (**NOTE: **At least on CC builds, reload is //not// enough, and you must //restart// to pickup new plugins and changes to existing plugins) | **NOTE:** At least on CC builds, reload is //not// enough, and you must ''restart'' to pickup new plugins and changes to existing plugins. |
| |