From 6481b1ff3231300dc2ccdd1b067fe687b5c054f2 Mon Sep 17 00:00:00 2001 From: niamtokik Date: Fri, 19 Jun 2020 16:23:43 +0000 Subject: [PATCH] started an article --- doc/using-libuv-with-erlang-c-node.md | 143 ++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 doc/using-libuv-with-erlang-c-node.md diff --git a/doc/using-libuv-with-erlang-c-node.md b/doc/using-libuv-with-erlang-c-node.md new file mode 100644 index 0000000..aeaa44d --- /dev/null +++ b/doc/using-libuv-with-erlang-c-node.md @@ -0,0 +1,143 @@ +# Using libuv with Erlang C-node + +> libuv is a multi-platform support library with a focus on +> asynchronous I/O. It was primarily developed for use by Node.js, but +> it’s also used by Luvit, Julia, pyuv, and others. + +Erlang is a great piece of software, with strong isolation and many +crazy features. Unfortunately, Erlang was not designed to execute +processes in other languages and to schedule the world outside of its +own universe. Some projects are already present on net, like +[`erlexec`](https://github.com/saleyn/erlexec), +[`alcove`](https://github.com/uselessd/alcove) or +[`exile`](https://github.com/akash-akya/exile) (in Elixir). Both of +these tools are good implementation and work pretty well but are not +portable. When you want to execute a process in an heterogeneous way, +you should probably use a more robust and tested library available on +the market. That why libuv is probably a great choice. + +libuv offers facilities to create an event loop, support tcp and udp +sockets (useless in our case), can deal with file system events, can +spawn processes, manages thread pool and uses signal handling. Well, +seems pretty nice. + +All this article was created and tested under OpenBSD-current and with +the last erlang relesease at time of writing, Erlang-R23. + +## Introduction to Erlang C-node + +If you are using Erlang, you should probably know Distributed Erlang, +a framework integrated with OTP to create distributed systems where an +Erlang virtual machine become a single node running multiple +processes. C-node is using the same principle but instead of running +an Erlang node, the node is coded in C. The library used to create +this relation with the remote node is called `libei` and present with +`erl_interface` module. To use this library, like any other C library, +`ei.h` must be available. + +```c +#include + +int +main(int argc, char *argv[]) { + return 0; +} +``` + +To compile this simple C code file, the path must be also given to the +compiler. + +``` +cc -L/usr/local/lib/erlang23/usr/lib \ + -I/usr/local/lib/erlang23/usr/include \ + -lei -o ${source}.c ${source} +``` + +### Connect to an Erlang node + +A c-node need to be initialized with different kind of variables, like +the name of the c-node (a string), the name of the target node (a +string based on the domain name of the node), a cookie (a secret +string shared with the c-node and the erlang node), and the date of +the creation. Erlang offers +[`ei_connect_init()`](https://erlang.org/doc/man/ei_connect.html#ei_connect_init) +function to initialize `ei_cnode` data structure, called `ec` in the +following code. + +When this data-structure is initialized, +[`ei_connect()`](https://erlang.org/doc/man/ei_connect.html#ei_connect) +function can be called. This function will try to reach the erlang +node and make a connection to it. At this moment in the execution +process, if a timer is created or an infinite loop is present, a +hidden node should be present on the erlang node. This can be checked +by executing `erlang:nodes(hidden)` and should return a list of the +hidden nodes connected. + +Finally, the [`shutdown()`](https://man.openbsd.org/man2/shutdown.2) +and [`close()`](https://man.openbsd.org/close) functions can be called +when the c-node goes away. Both of these functions are present in the +standard C library. + +```c +#include // fprintf() +#include +#include // ei_connect_init(), ei_connect() +#include // time() +#include // shutdown() +#include // close() + +int +main(int argc, char *argv[]) { + /* name of the c-node /* + char *node_name = ""; + + /* erlang node name */ + char *target_node; + + /* cookie used to connect to erlang node */ + char *cookie = ""; + + /* time's creation of the node */ + char creation = time(NULL)+1; + + /* ei_cnode structure contains node's information */ + ei_cnode ec; + + /* connect to erlang node with previous variable */ + ei_connect_init(&ec, node_name, cookie, creation); + + /* open file descriptor, a reference to the connection */ + int sockfd; + sockfd = ei_connect(&ec, node_target)) + if (sockfd != 0) + fprintf(stderr, "ERROR: ei_connect failed\n"); + + /* stop the connection */ + shutdown(sockfd, 1); + + /* close the socket */ + close(sockfd); + + return 0; +} +``` + +### Sending a message to an Erlang node + +### Receiving a message from an Erlang node + +## Introduction to libuv + +# Resources + +## Libuv + + * http://docs.libuv.org/en/v1.x/ + * https://github.com/trevnorris/libuv-examples + +## Erlang + + * https://erlang.org/doc/apps/erl_interface/ei_users_guide.html + * https://erlang.org/doc/apps/erl_interface/index.html + * https://github.com/erlang/otp/tree/master/lib/erl_interface/test +