# Broker API update

**URL:** <https://community.zeek.org/t/broker-api-update/4221>\
**Category:** Development\
**Tags:** development\
**Created:** [July 1, 2016, 6:24pm UTC](https://community.zeek.org/t/broker-api-update/4221 "2016-07-01T18:24:52Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Matthias\_Vallentin1](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/matthias_vallentin1/32/596_2.png) [@Matthias\_Vallentin1](https://community.zeek.org/u/Matthias_Vallentin1)\
**Post date:** [July 1, 2016, 6:24pm UTC](https://community.zeek.org/t/broker-api-update/4221/1 "2016-07-01T18:24:52Z")

</div>

Here's a brief update about the recent changes to the Broker API update.  
For more examples, you can look at the unit tests [1]. I'm also  
attaching a small graphic that illustrates the architecture from a high  
level.

Fundamentally, endpoints represent processing units that exchange  
messages. An endpoint processes one message at a time, but all endpoints  
execute in paralell---similar to the actor model. Each message has  
associated a topic and endpoints deliver messages according to their  
subscriptions and peerings. Unlike in the previous version, there is no  
more global state: each endpoints lives in a context.

There exist two types of endpoints: blocking and nonblocking. The former  
features a synchronous interface where users have to manually extract  
messages from the endpoint. Messages accumulate in the endpoint's  
"mailbox" until extracted. On the contrary, a nonblocking endpoint  
executes a callback for each message it receives. Here's a code snippet:

&nbsp;&nbsp;context ctx;  
&nbsp;&nbsp;auto e0 = ctx.spawn\<blocking\>();  
&nbsp;&nbsp;auto e1 = ctx.spawn\<nonblocking\>(  
&nbsp;&nbsp;&nbsp;&nbsp;[](const topic&, const message&) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Inspect topic t and/or process message.  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;);

&nbsp;&nbsp;// Establish a peering between two endpoints.  
&nbsp;&nbsp;e0.peer(e1);

&nbsp;&nbsp;// Subscribe to some topics. The subscribing endpoint will relayed its  
&nbsp;&nbsp;// subscriptions to all known peers.  
&nbsp;&nbsp;e0.subscribe("/foo");  
&nbsp;&nbsp;e0.subscribe("/bar");

&nbsp;&nbsp;// Block and wait until a message arrives according to the endpoint's  
&nbsp;&nbsp;// subscriptions.  
&nbsp;&nbsp;e0.receive(  
&nbsp;&nbsp;&nbsp;&nbsp;[](const topic&, const message&) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Inspect topic t and/or process message.  
&nbsp;&nbsp;&nbsp;&nbsp;},  
&nbsp;&nbsp;&nbsp;&nbsp;[](const status& s) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Process status messages, such as new/lost peers  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;);

Broker will only allow messages that contain instances of data, which is  
a sum type and can be any of the types in Bro's data model. In the  
future, we may loosen this restriction to allow users sending their own  
custom types over the same Broker communication channel. But for we  
enforce this requirement. This is the API to send messages:

&nbsp;&nbsp;// Send a message of type \<integer, real, count\> under topic /foo.  
&nbsp;&nbsp;e1.publish("/foo", 42, 4.2, 42u);

&nbsp;&nbsp;// Construct a message of type \<string, vector\> and sends it away.  
&nbsp;&nbsp;auto msg = make\_data\_message("foo", vector{42, nil, 44});  
&nbsp;&nbsp;e1.publish("/foo", msg);

You will get a compile error if the arguments to make\_data\_message or  
publish are not unambiguously convertible to one of the types in  
Broker's data model.

To cross process boundaries, endpoints can use TCP communication as  
follows:

&nbsp;&nbsp;// In one process.  
&nbsp;&nbsp;context ctx;  
&nbsp;&nbsp;auto e = ctx.spawn\<...\>();  
&nbsp;&nbsp;e.listen("127.0.0.1", 42000);

&nbsp;&nbsp;// In another process.  
&nbsp;&nbsp;context ctx;  
&nbsp;&nbsp;auto e = ctx.spawn\<...\>();  
&nbsp;&nbsp;e.peer("127.0.0.1, 4200);

If one would "accidentally" establish a TCP connection between endpoints  
in the same process, the runtime would detect this scenario and avoid  
costly message serialization and use "pointer passing" instead.

On my todo list for the next couple of weeks are (in order):

&nbsp;&nbsp;&nbsp;&nbsp;(0) Fix remaining bugs (mostly CAF)  
&nbsp;&nbsp;&nbsp;&nbsp;(1) Adapt data stores to the new API  
&nbsp;&nbsp;&nbsp;&nbsp;(2) Create Python bindings via pybind11  
&nbsp;&nbsp;&nbsp;&nbsp;(3) Perform the "engine swap" in Bro  
&nbsp;&nbsp;&nbsp;&nbsp;(4) Extensive unit and performance testing  
&nbsp;&nbsp;&nbsp;&nbsp;(5) Update documentation à la CAF [2]

Moreover, I'm already in touch with Mathias Fischer regarding multi-hop  
subscription management. For now, we have a single-hop peerings, i.e.,  
if a peering of the form A \<-\> B \<-\> C exists, A relays a subscription  
change only to B. See Mathias' email for more details on this topic.

&nbsp;&nbsp;&nbsp;&nbsp;Matthias

[1] [broker/tests/cpp at topic/matthias/actor-system · bro/broker · GitHub](https://github.com/bro/broker/tree/topic/matthias/actor-system/tests/cpp)  
[2] [CAF User Manual — CAF 0.18.6-dev+exp.sha.1ea3128 documentation](http://actor-framework.readthedocs.io/en/latest/)

 ![architecture.png](https://canada1.discourse-cdn.com/flex011/uploads/zeek/original/1X/51da2fed5f6aa9b1e3051b621dfa8e861836a2c1.png)

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex011/uploads/zeek/original/1X/f09d732bc2cc7c7cc7e35db67cf4e1d5233ce7a7.png) [@system](https://community.zeek.org/u/system)\
**Post date:** [May 6, 2022, 3:43pm UTC](https://community.zeek.org/t/broker-api-update/4221/2 "2022-05-06T15:43:48Z")

</div>


