|
| 1 | +--- |
| 2 | +sidebar_position: 10 |
| 3 | +--- |
| 4 | +# Bootstrapping |
| 5 | + |
| 6 | +In the [previous section](../getting-started.md), we learned how to use the `DrasylNode` class — a |
| 7 | +minimalist interface to integrate drasyl into your application. |
| 8 | +It provides rich flexibility through customization, configuring the node that best fits your use case. |
| 9 | +But for some use cases, you may want to customize your node even further. |
| 10 | +For this, we provide a Bootstrapping interface, a more powerful way to create a drasyl node. |
| 11 | + |
| 12 | +To help understand the Bootstrapping interface, we first want to give the background some information on |
| 13 | +the technical internals of drasyl and the applied concepts. |
| 14 | + |
| 15 | +## Background: Netty Concepts |
| 16 | + |
| 17 | +The core of drasyl is built with [Netty](https://netty.io/). |
| 18 | +Netty describes itself as "an asynchronous event-driven network application framework for rapid |
| 19 | +development of maintainable high performance protocol servers & clients". |
| 20 | +To this end, Netty defines an architectural model and a rich set of design patterns for network |
| 21 | +programming. |
| 22 | + |
| 23 | +### `Channel`s |
| 24 | + |
| 25 | +One of Netty's primary building block is the `Channel`. A `Channel` is a [basic construct of Java NIO](https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Channel.html). |
| 26 | +It represents |
| 27 | +> an open connection to an entity such as a hardware device, a file, a network socket, or a program |
| 28 | +> component that is capable of performing one or more distinct I/O operations, for example reading |
| 29 | +> or writing. |
| 30 | +
|
| 31 | +Netty uses this `Channel` interface mainly for IP-based transports like TCP or UDP. |
| 32 | +drasyl has adopted this concept and provides a unified interface for communication with peers, regardless of their location and route. |
| 33 | + |
| 34 | +### Events Handlers |
| 35 | + |
| 36 | +Netty (and therefore drasyl) uses distinct events to notify your application about status changes of the channel or issues operations. |
| 37 | +This allows your application to react with the appropriate action based on the type of occurring event (e.g., logging, data transformation, flow-control, business logic, etc.). |
| 38 | + |
| 39 | +To control what actions your application should apply, each `Channel` applies the interceptor design pattern. |
| 40 | +That means that you can register a given number of interceptors (so-called [`ChannelHandler`](https://livebook.manning.com/book/netty-in-action/chapter-6/)s) to a channel, performing independently various. |
| 41 | +These `ChannelHandler`s can be added, removed, and resorted to at any time for each `Channel`. |
| 42 | +Netty provides an extensive set of predefined handlers, most of which are compatible with drasyl! |
| 43 | + |
| 44 | +### Bootstrapping |
| 45 | + |
| 46 | +[Bootstrapping](https://livebook.manning.com/book/netty-in-action/chapter-8/) defines the startup code configuring the `Channel`. |
| 47 | +At a minimum, it binds the node to a given overlay identity on which it will listen for connection requests. |
| 48 | + |
| 49 | +To learn more about Netty, the used concepts, and how to use them, we recommend reading the |
| 50 | +[Netty User Guide](https://netty.io/wiki/user-guide.html) as well as the book "Netty in Action" by |
| 51 | +Marvin Wolfthal and Norman Maurer. |
| 52 | + |
| 53 | +## Create Node using Bootstrapping |
| 54 | + |
| 55 | +First, we need to create a `ServerBootstrap` object that describes the behavior of our drasyl node. |
| 56 | +The `TraversingDrasylServerChannelInitializer` is a special `ChannelHandler` that conveniently |
| 57 | +populates other handlers necessary for the minimal operation of a drasyl node. |
| 58 | +The implementation of `ChannelInitializer` in the following line defines how to handle received data |
| 59 | +from other peers. In this case, they are interpreted and output as a string. |
| 60 | + |
| 61 | +```java title="Bootstrapping.class" |
| 62 | +import io.netty.bootstrap.ServerBootstrap; |
| 63 | +import io.netty.buffer.ByteBuf; |
| 64 | +import io.netty.channel.*; |
| 65 | +import io.netty.channel.nio.NioEventLoopGroup; |
| 66 | +import org.drasyl.channel.*; |
| 67 | +import org.drasyl.identity.Identity; |
| 68 | +import static java.nio.charset.StandardCharsets.UTF_8; |
| 69 | + |
| 70 | +public class Bootstrapping { |
| 71 | + public static void main(final String[] args) { |
| 72 | + final Identity identity = /* code */; |
| 73 | + |
| 74 | + // highlight-start |
| 75 | + final NioEventLoopGroup group = new NioEventLoopGroup(); |
| 76 | + final ServerBootstrap b = new ServerBootstrap() |
| 77 | + // we want to create a drasyl-based channel (not UDP or TCP). |
| 78 | + .channel(DrasylServerChannel.class) |
| 79 | + // create and assign a thread pool dedicated to proccess in- and outbound data. |
| 80 | + .group(group) |
| 81 | + // ChannelHandler in charge of performing all control plane-related operations. |
| 82 | + // There is only one server channel per node. |
| 83 | + .handler(new TraversingDrasylServerChannelInitializer(identity)) |
| 84 | + // ChannelHandler in charge of performing all data plane-related operations. |
| 85 | + // There is a child channel for each peer. |
| 86 | + .childHandler(new ChannelInitializer<DrasylChannel>() { |
| 87 | + @Override |
| 88 | + protected void initChannel(final DrasylChannel ch) { |
| 89 | + final ChannelPipeline p = ch.pipeline(); |
| 90 | + |
| 91 | + p.addLast(new SimpleChannelInboundHandler<ByteBuf>() { |
| 92 | + @Override |
| 93 | + protected void channelRead0(final ChannelHandlerContext ctx, |
| 94 | + final ByteBuf msg) { |
| 95 | + System.out.println("Got `" + msg.toString(UTF_8) + "` from `" + ctx.channel().remoteAddress() + "`"); |
| 96 | + } |
| 97 | + }); |
| 98 | + } |
| 99 | + }); |
| 100 | + // highlight-end |
| 101 | + } |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +Now that the "recipe" for our drasyl node has been defined, we can start it and wait for messages to |
| 106 | +arrive. |
| 107 | + |
| 108 | +```java title="Bootstrapping.class" |
| 109 | +import io.netty.bootstrap.ServerBootstrap; |
| 110 | +import io.netty.buffer.ByteBuf; |
| 111 | +import io.netty.channel.*; |
| 112 | +import io.netty.channel.nio.NioEventLoopGroup; |
| 113 | +import org.drasyl.channel.*; |
| 114 | +import org.drasyl.identity.Identity; |
| 115 | +import static java.nio.charset.StandardCharsets.UTF_8; |
| 116 | + |
| 117 | +public class Bootstrapping { |
| 118 | + public static void main(final String[] args) { |
| 119 | + /* code */ |
| 120 | + |
| 121 | + try { |
| 122 | + // highlight-start |
| 123 | + // create new node with given identity. |
| 124 | + final Channel ch = b.bind(identity.getAddress()).syncUninterruptibly().channel(); |
| 125 | + System.out.println("Node listening on address " + ch.localAddress()); |
| 126 | + // wait for node to stop. |
| 127 | + ch.closeFuture().awaitUninterruptibly(); |
| 128 | + // highlight-end |
| 129 | + } |
| 130 | + finally { |
| 131 | + // ensure that thread pool is shutdown |
| 132 | + group.shutdownGracefully(); |
| 133 | + } |
| 134 | + } |
| 135 | +} |
| 136 | + |
| 137 | +``` |
| 138 | + |
| 139 | +## Example |
| 140 | + |
| 141 | +A fully working example can be found |
| 142 | +here: [EchoServerBootstrap](https://github.com/drasyl/drasyl/blob/master/drasyl-examples/src/main/java/org/drasyl/example/echo/EchoServerBootstrap.java) |
0 commit comments