WARNING

This is a draft

Node by barnaulsky-zeek Node (opens new window) by barnaulsky-zeek (opens new window)

It was a long time I did not write an article about Erlang. To long for me. Do you remember my last article? It was 2 years ago, in 2017. I wrote an article on how to craft yourself ETF (External Term Format) and BERT (Binary Erlang Term) in C. This was a — not so — lite introduction on what is and how to use this serialization method instead of classical JSON or XML in a low level fashion. After this last article I wanted to write another “paper” to show you how to connect a Perl node with an Erlang one. Unfortunately, I did not find enough time to end this long article…

Today, after this long period of inactivity without writing anything useful for Erlang, I decided to write a new article on this subject. The BEAM virtual machine is a pretty famous piece of software and offers a wide range of facilities to connect it to different languages like Java or C natively. Recently, many people were interested on dissecting it and give me the will of doing something. If you are reading this article, you are probably interested in Erlang/Elixir and should know that everything on these two languages are about message passing. In this article, I will try to explain how works a C node and how to send data though from/to C node and Erlang/Elixir involving message passing.

Actually, I am still not a specialist in C. I know a little about Erlang, but I can call me a “true” expert, thanks humility, it gives me sufficient resource to keep learn new things. As usual, I will learn a lot with you, and try to learn the hard way by reading official documentation, though written test cases, reading existing source code and writing my own crappy code. Before starting anything, we will first answer a question, what is a C node?

A C node is a C program written to act as a hidden node in a distributed Erlang system. The library Erl_Interface contains functions for this purpose. For more information about C nodes. From Erlang’s point of view, the C node is treated like a normal Erlang node.

Why using C node? Erlang loves strong isolation, small processes doing one single task and doing it well. Every part of this language was made of small pieces interconnected together. If you need to share information, you must send a message. A C node can help you to offer new specific facilities to an Erlang running node.

A C node connected to classical one is always hidden, it means that this external node can only be seen by one node and not the others. Here the definition of what is an hidden node from the documentation.

A hidden node is a node started with the command-line flag -hidden. Connections between hidden nodes and other nodes are not transitive, they must be set up explicitly. Also, hidden nodes does not show up in the list of nodes returned by nodes(). Instead, nodes(hidden) or nodes(connected) must be used. This means, for example, that the hidden node is not added to the set of nodes that global is keeping track of.

All code on this article runs with Erlang-R21 and OpenBSD-Current (6.4+).

# Distributed Erlang

Networkby PopiX Network (opens new window) by PopiX (opens new window)

  • explain EPMD protocol (create a schema, cookie, handshare, ssl and security)

  • connecting Erlang node (create a video with asciinema and code sample)

  • connect C nodes (how to send and receive messages, sample code)

  • show different implementation (Go, Rust, C…)

Erlang is a distributed language, it creates an easy way to interconnect different nodes between them. If we are talking about connecting things then we need to talk about protocols. Actually, Erlang nodes are using EPM (Erlang Port Mapper).

The good old way to interconnect nodes with Erlang is to invoke the REPL with some specific flags

It is a bit difficult to give you the possibility to show you how the different nodes are connecting together. Maybe a good way is to create a record of all the command typed on the prompt

Have you ever tried in your main programming language to connect different part of your code together. Usually, you will use a message passing protocol (e.g. AMPQ) or something to store shared data across nodes (e.g. NoSQL or SQL). Erlang offers all the required protocols and tools to easily connect nodes together easily. It is not surprise why RabbitMQ is developped in Erlang, or other distributed database like Riak.

$ erl -sname one -setcookie "MyBeautifulCookie"

and now the code used to connect to different nodes

net\_kernel:connect\_node('two@yourhostname').  
nodes().

# Looking Around

Through the Looking Glass by wreck-photography Through the Looking Glass (opens new window) by wreck-photography (opens new window)

Hopefully, OTP programmers have good practices. We have access to good example with erl_call for example, who use erl_interface to communicate with a node. We can also found unit testing code and lot of documentation about the interfaces.

I found also some code example on Github and alternative solution for other languages (Rust and Go).

# Common and Shared Functions/Data-Structures

Shared Base by EmmmBeee Shared Base (opens new window) by EmmmBeee (opens new window)

Mono-threaded and multi-threaded code will share many common functions, a good way to don’t repeat our self is to create a library containing all required functions. So, what do we need?

  • A way to craft messages: we don’t want to create a fully compatible C node with all message type, we only need some specific functions to craft common messages, like all is okay or something goes wrong.

  • A way to send messages: sending message is straightforward even on a C node, but, because we will use only few function to craft messages, we will create a specific function to send them.

  • A way to receive messages: our Erlang will send us message, without doubt. We need a way to catch them and parse them in an easy way.

  • A way to manage buffers: as you may know, C programming is about memory and buffers. I usually prefer to use stack instead of heap. In our example case, it would be great to add more buffer mode and management features.

  • A way to add more functions: creating dynamic code in C is complicated, but we can find an easy way to create new function as callback. That a bonus step.

# Mono-Threaded C

along a thread by ZER0–0NE along a thread (opens new window) by ZER0–0NE (opens new window)

  • Create first connection
  • Send and receive data
  • Close the connection

A good way to learn is to decompose complex problem in small simple problems. Using concurrent programming (threading) in all language is actually hard. Keep it simple: we will create a simple monothread C program and try to interact with an Erlang node.

# Multi-Threaded C

Threads of Life by stengchen Threads of Life (opens new window) by stengchen (opens new window)

  • pthread
  • Create a connection
  • Send and receive data
  • Close the connection

No one like multi-threading, and if you like it, I think you are a little crazy person. Multi-threading adds lot of complexity in our code by “duplicating” the tasks. I like Erlang because it makes the concurrent and parallel programming easily accessible to anybody.

Multi-threading is hard. No one like it. It adds lot of complexity in our code and puts

# Code Testing

Testing..testing…. by thrumyeye Testing..testing…. (opens new window) by thrumyeye (opens new window)

Test Driven Development (TDD) is probably the best method to write code and avoid lot of mistakes. It will not do everything for you, but will help you to create interface and, if you don’t have time to write doc, give you some example.

# Building C Code with Makefile

Automation Say It Word by lovelywilly Automation Say It Word (opens new window) by lovelywilly (opens new window)

  • mono-thread
  • multi-thread
  • debug-mode

Writing C code and building it without error is not so easy. GCC or LLVM/Clang compilers have a huge amount of flags to modify the generated code. Here I will use GNU Makefile to automatize the build. I usually prefer pmake, the default one on OpenBSD, but, pmake is not available on all systems.

The code we will write will be pretty straightforward for the people using daily Erlang or C code. Working on OpenBSD, you need to install gnumake and one Erlang release from official repositories or ports (R16, R18,R19 or R21). Every data are present in the path /usr/local/lib/erlang${EREL}/ . Builded library objects are presents in /usr/local/lib/erlang${EREL}/usr/lib and the C headers are presents in /usr/local/lib/erlang${EREL}/usr/include .

# Cocoon of Charming Features

Orb weaver mama laying eggs by melvynyeo Orb weaver mama laying eggs (opens new window) by melvynyeo (opens new window)

Interoperability and interfacing are complicated things. A lot of projects tried to created different ways to make that possible. Erlang/OTP gives us here a lot of facilities to play with different languages and gives the opportunity to connect them together through a message passing interface.

2 years ago, I was thinking on a good way to create strong isolation for security features.

I wanted to play with this method of interfacing for lot of reasons. Firstly, on my last article written 2 years ago, I was thinking on a way to isolate things. Firstly, I was thinking to add features in NIF, but, it was not really a good idea. Secondly, I was thinking to create a simple C code connected as Port, it was a better idea. Finally, creating a C nodes can create a strong isolation by using a common network protocol between each nodes. There is still an issue, the standard Erlang method to connect nodes does not give use the ability to filter requests or do thin grained authentication.

# Resources

Library by vladstudio Library (opens new window) by vladstudio (opens new window)

# Notes

Notepad by CupcakeGerbil Notepad (opens new window) by CupcakeGerbil (opens new window)

This article is a little different from the past ones. I wanted to create an article with pictures coming from different places on the web and maybe give you the envy to discover new artists from around the world. I think today technology should add more “dreams”. After my last long trip for 4 months, I figured out that only a few amount of people really care about low level programming and a few more don’t even care about beautiful code. Maybe adding a small part of artistic thingies can change that? Who know…

# Thanks

thanks. by kariiissa thanks. (opens new window) by kariiissa (opens new window)

Many thanks to the beautiful Erlang community and its amazing documentation. Every time I re-work with, it always a pleasure! As usual, thanks to OpenBSD community, to keep a system clean and really easy to use. I don’t have enough vocabulary and words to say that your works are awesome.

Don’t hesitate to follow me on my different social network, niamtokik on Twitter or archemisc on Twitch. See you!