<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>Hintjens</title>
		<link>http://hintjens.wikidot.com</link>
		<description></description>
				<copyright></copyright>
		<lastBuildDate>Fri, 13 Mar 2026 17:56:38 +0000</lastBuildDate>
		
					<item>
				<guid>http://hintjens.wikidot.com/blog:93</guid>
				<title>C4.1 - an Exothermic Process</title>
				<link>http://hintjens.wikidot.com/blog:93</link>
				<description>

&lt;p&gt;In February 2012 the ZeroMQ community said &amp;quot;adieu&amp;quot; to its long time maintainers, and set sail in a new direction. Using a &lt;a href=&quot;http://rfc.zeromq.org/spec:22&quot;&gt;new process&lt;/a&gt; called C4.1 as its compass, we headed off into unknown territory. Looking back three and a half years later, what is the result? Did ZeroMQ lose its way, as many predicted and feared? Or did the new process work as planned?&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 16 Sep 2015 20:49:16 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>In February 2012 the ZeroMQ community said &quot;adieu&quot; to its long time maintainers, and set sail in a new direction. Using a <a href="http://rfc.zeromq.org/spec:22">new process</a> called C4.1 as its compass, we headed off into unknown territory. Looking back three and a half years later, what is the result? Did ZeroMQ lose its way, as many predicted and feared? Or did the new process work as planned?</p> <p>C4.1 claims its first goal is to &quot;maximize the scale of the community around a project.&quot; Community means many things. Above all it means life. If no-one uses or contributes to your software, the code does not matter.</p> <p>Here is my analysis of the growth of the ZeroMQ community since we moved to git in mid-2009:</p> <a href="http://hintjens.com/local--files/blog:93/graph.png"><img src="http://hintjens.wdfiles.com/local--files/blog:93/graph.png" width="500" alt="graph.png" class="image" /></a> <p>The picture speaks volumes. You can see the activity grow, peak, and slow down for each major version. You can see the clear difference between &quot;before&quot; and &quot;after&quot; the fork in late 2011, when the original maintainers left to create Crossroads.io, and ZeroMQ moved to the C4.1 process.</p> <p>What is most fun is that ZeroMQ takes zero management these days. It is self-steering, self-feeding, and self-organizing. We have applied C4.1 to old projects like libzmq, and brand new ones. The results are the same. If the project does something useful, it takes off, and contributors join, and everyone enjoys themselves.</p> <p>C4.1 is an exothermic process. It produces almost perfect software. ZeroMQ's oddities all date from before 2012, and are slowly disappearing. ZeroMQ master is almost always stable. It just does not break stable APIs or protocols. The mailing list is polite and happy. We do not argue.</p> <p>If you run an open source project, and your commit chart does <em>not</em> look like this, go read <a href="http://rfc.zeromq.org/spec:22">ZeroMQ RFC 22</a>.</p> <p>Here is how I produced this chart:</p> <ul> <li>Take all of the repositories in the ZeroMQ organization on github. There are many times more projects that aren't in the organization (about 20 for each one in the organization). I ignored these. There are &quot;stabilization forks&quot; of projects, like zeromq4-x. I ignored these as well.</li> </ul> <ul> <li>Clone each repository to my laptop, then listed all commits since the start, using this command: <tt>git log &#8212;date=short &#8212;format=&quot;format:%ad&quot;</tt>, for each project.</li> </ul> <ul> <li>Get the number of commits per day using this command: <tt>sort activity.log | uniq -c</tt></li> </ul> <ul> <li>Run a Perl script that calculates the totals per week, and prints out a comma-separated values file.</li> </ul> <ul> <li>Load that into LibreOffice and generate a graphic.</li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:86</guid>
				<title>A Protocol for REST over ZeroMQ</title>
				<link>http://hintjens.wikidot.com/blog:86</link>
				<description>

&lt;p&gt;In this article I&#039;ll descibe a popular way of making really awful protocols, using &amp;quot;RPC&amp;quot; or Remote Procedure Calls. My goal is to teach you to never use RPC, ever again. As a safer and saner alternative I&#039;ll explain how to do RESTful work over ZeroMQ.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 09 Feb 2015 10:51:03 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>In this article I'll descibe a popular way of making really awful protocols, using &quot;RPC&quot; or Remote Procedure Calls. My goal is to teach you to never use RPC, ever again. As a safer and saner alternative I'll explain how to do RESTful work over ZeroMQ.</p> <h2><span>What's the Problem?</span></h2> <p>The other day a friend asked me what the limit was on zproto's command numbering. My spidey sense immediately flashed, &quot;Danger!&quot; When someone asks &quot;is it normal that the cat makes that strange noise?&quot; the prudent person asks, &quot;what precisely are you doing to the poor animal?&quot; So it also goes for protocol tools like zproto.</p> <p>Let me start by saying, if your protocol has even dozens, let alone hundreds, of commands, then you are Doing it Wrong. What &quot;wrong&quot; means is that you'll end up spending more time and money than you need to. Not in a good way either. While buying a nice, <em>really good</em> pair of shoes can be cathartic, there is nothing healing about telling your boss, &quot;sorry, we can't make that essential change because it would break everything.&quot;</p> <p>We sometimes mix the concepts of &quot;API&quot; and &quot;protocol&quot;. I've done this myself, designing protocols that looked like APIs, and designing APIs that act like protocols. However it's like putting ginger in a curry. The art is to add spice without breaking the taste of the dish.</p> <p>There are good APIs and there are poor APIs. A good API at least organizes itself into silos, which we can call &quot;packages&quot; or &quot;classes&quot;. The poorly-designed API is typically one large bundle of loosely related methods. However, both map to nasty, fragile protocols.</p> <p>Let me show with an example. AMQP (my favorite example of smart people making stupid mistakes) had server-side objects like &quot;exchange&quot; and &quot;binding&quot;. So the API-protocol fudge had methods like &quot;exchange.declare&quot; and &quot;binding.delete&quot;. On the plus side, the protocol was neatly organized into silos, and was easy to use as an API.</p> <p>On the minus side, it was fragile as heck. The prime directive of every protocol should be &quot;Interoperate!&quot;, and AMQP could not even interoperate with itself. AMQP/0.9.1 did not talk to AMQP/0.8. Let's not mention the alien invader that is currently wearing AMQP's face in public.</p> <p>APIs have some endearing properties:</p> <ul> <li>They change often, because they are mapped closely to business language that is constantly evolving.</li> <li>When you use the wrong version, they tend to crash.</li> </ul> <p>True, some platforms have managed to keep compatibility over decades. Windows and Linux, for instance. There can be a lot of pain involved.</p> <p>More usually, though, when we turn an API with hundreds of methods into a protocol, we create a monster. If the monster dies rapidly, fine. If the monster lives and grows, that means real trouble ahead.</p> <p>In a distributed system, it is <em>essential</em> to be able to evolve pieces independently. This also means evolving the business semantics independently across different parts of the system. Once you cast these semantics into protocols, that becomes approximately impossible.</p> <p>With AMQP we could evolve the protocol for a few years because (a) it was not a real distributed system, all clients talking to central brokers, and (b) we could make brokers like OpenAMQ and RabbitMQ talk several versions of the protocol. Even then, the cost of change was so insanely high that we simply froze the protocol, and then it died (perhaps from frostbite).</p> <h2><span>Hell is Large Contracts</span></h2> <p>Beware of large integrated contracts. Do you really want your electricity, Internet, coffee, and cat food from a single supplier, on one contract? There's a reason monopolists and cartels love &quot;bundling&quot; and consumers hate them. It raises the switching costs (&quot;I have a better catfood supplier&quot;) and so lets the supplier raise costs overall.</p> <p>What we want are small, focussed contracts with the right level of abstraction. Heck, we don't even need very good contracts at the start. If switching costs are low to zero, we can improve individual contracts cheaply over time.</p> <p>Back to AMQP as example. The protocol raised server objects like &quot;exchange&quot;, &quot;binding&quot;, &quot;queue&quot;, and &quot;consumer&quot; to first class entities. Adding, removing, or changing these had the effect of changing the whole contract. Making a single tweak to any of these broke interoperabilty for everything.</p> <p>This is what you get when you map an API (even one that's neatly designed) to a network protocol. A large, fragile contract that punishes experimentation and evolution, and creates pseudo-distributed systems you cannot improve gradually over time.</p> <h2><span>The Resource Abstraction</span></h2> <p>The answer I'm going to present — it's not the only one, yet it's a good one — is old and surprisingly boring. That is, instead of presenting your business objects as a set of objects with arbitrary methods and properties, use abstract resources.</p> <p>With abstract resources we need only four methods: create, fetch, update, and delete. A resource is then a document (using a self-describing format like XML or JSON). Resources can be nested. Instead of executing methods on objects, we modify properties on a resource.</p> <p>The best known design for this is REST, based on HTTP. It uses POST, GET, PUT, and DELETE for method names, and a host of headers like &quot;If-Modified-Since&quot; to condition how these work. RESTful APIs (so-called) are in fact decent protocols. Take a look <a href="http://developer.openstack.org/api-ref-compute-v2.html">at the OpenStack Compute API</a>. You can see that there are dozens of distinct contracts. Requests and responses are both extensible by design.</p> <h2><span>Mapping REST to ZeroMQ</span></h2> <p>We can design a generic RESTful access protocol and map it to ZeroMQ. We did the foundation work some years ago <a href="http://www.restms.org/spec:1">for RestMS</a>. I don't think many people picked that up at the time. However today it looks quite useful for ZeroMQ applications struggling with how to design their protocols.</p> <p>Our generic use case is a server that holds a set of resources belonging to, and managed by, a set of remote clients. We wish to build APIs, based on network protocols that allow clients and servers to be distributed across both local and wide area networks. We hold that such protocols are essential for the clean separation of components of a distributed architecture.</p> <p>Protocols define agreed and testable contracts. Our resource access protocol has two levels of contract:</p> <ul> <li>Agreement on the resources that the server provides; the names and properties, and semantics of such resources; and their relationship to one another. This consists of any number of independent &quot;resource schemas&quot;.</li> </ul> <ul> <li>Agreement on how to represent resources on the wire, how to navigate the resource schema, create new resources, retrieve resources, return errors, and so on. This is the &quot;access protocol&quot;, which XRAP provides.</li> </ul> <p>The main goal of XRAP is to make it extremely cheap to develop, test, improve, and discard resource schemas. That is, to allow specialists in this domain to develop good schemas with minimal marginal cost. XRAP achieves this economy is by splitting off, and independently solving the access protocol.</p> <ul> <li>In technical terms, it allows the provision of 100% reusable solutions (libraries and internal APIs in arbitrary languages) for the access and transport layers.</li> </ul> <ul> <li>In specification terms, it allows the formal specification of schemas as small independent RFCs.</li> </ul> <p>Here is the XRAP encoding over ZeroMQ:</p> <div class="code"> <pre><code>xrap_msg = *( POST | POST-OK | GET | GET-OK | GET-EMPTY | PUT | PUT-OK | DELETE | DELETE-OK | ERROR ) ; Create a new, dynamically named resource in some parent. POST = signature %d1 parent content_type content_body signature = %xAA %xA5 ; two octets parent = string ; Schema/type/name content_type = string ; Content type content_body = longstr ; New resource specification ; Success response for POST. POST-OK = signature %d2 status_code location etag date_modified content_type content_body status_code = number-2 ; Response status code 2xx location = string ; Schema/type/name etag = string ; Opaque hash tag date_modified = number-8 ; Date and time modified content_type = string ; Content type content_body = longstr ; Resource contents ; Retrieve a known resource. GET = signature %d3 resource if_modified_since if_none_match content_type resource = string ; Schema/type/name if_modified_since = number-8 ; GET if more recent if_none_match = string ; GET if changed content_type = string ; Desired content type ; Success response for GET. GET-OK = signature %d4 status_code content_type content_body status_code = number-2 ; Response status code 2xx content_type = string ; Actual content type content_body = longstr ; Resource specification ; Conditional GET returned 304 Not Modified. GET-EMPTY = signature %d5 status_code status_code = number-2 ; Response status code 3xx ; Update a known resource. PUT = signature %d6 resource if_unmodified_since if_match content_type content_body resource = string ; Schema/type/name if_unmodified_since = number-8 ; Update if same date if_match = string ; Update if same ETag content_type = string ; Content type content_body = longstr ; New resource specification ; Success response for PUT. PUT-OK = signature %d7 status_code location etag date_modified status_code = number-2 ; Response status code 2xx location = string ; Schema/type/name etag = string ; Opaque hash tag date_modified = number-8 ; Date and time modified ; Remove a known resource. DELETE = signature %d8 resource if_unmodified_since if_match resource = string ; schema/type/name if_unmodified_since = number-8 ; DELETE if same date if_match = string ; DELETE if same ETag ; Success response for DELETE. DELETE-OK = signature %d9 status_code status_code = number-2 ; Response status code 2xx ; Error response for any request. ERROR = signature %d10 status_code status_text status_code = number-2 ; Response status code, 4xx or 5xx status_text = string ; Response status text ; Strings are always length + text contents string = number-1 *VCHAR longstr = number-4 *VCHAR ; Numbers are unsigned integers in network byte order number-1 = 1OCTET number-2 = 2OCTET number-4 = 4OCTET number-8 = 8OCTET</code></pre></div> <p>I've written this up as <a href="http://rfc.zeromq.org/spec:40">a draft on the ZeroMQ RFC website</a>. There is <a href="https://github.com/zeromq/rfc/blob/master/src/spec_40.xml">a zproto model</a> for the protocol if you want to experiment.</p> <h2><span>Conclusions</span></h2> <p>While it's become easy to build RPC protocols using tools like protobufs and zproto, many of these protocols tend to be fragile and expensive to evolve across a distributed system. That becomes a problem at scale. The root cause is the lack of abstraction, so that every change to business semantics causes a break in the protocol, and a new version.</p> <p>One proven way to address this is to use a RESTful resource approach, instead of RPC. This provides equivalent semantics, yet is designed to handle change naturally, and cheaply.</p> <p>In this article I've presented a new protocol called XRAP, which provides a RESTful approach over ZeroMQ. XRAP is still a draft specification and under development. If you want to use it, contact me and we'll work together on this.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:85</guid>
				<title>The End of Software Versions</title>
				<link>http://hintjens.wikidot.com/blog:85</link>
				<description>

&lt;p&gt;Software version numbers are the crack cocaine of change management. They are an easy and attractive path to serious long term stress and pain. The worst ever distress in the ZeroMQ community came from allowing library version numbers to define compatibility. The reasons are real, yet subtle and often counter-intuitive. In this article I&#039;ll explain in detail, and propose a replacement for software versioning.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 06 Feb 2015 14:20:05 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Software version numbers are the crack cocaine of change management. They are an easy and attractive path to serious long term stress and pain. The worst ever distress in the ZeroMQ community came from allowing library version numbers to define compatibility. The reasons are real, yet subtle and often counter-intuitive. In this article I'll explain in detail, and propose a replacement for software versioning.</p> <table style="margin:0; padding:0"> <tr> <td style="margin:0; padding:0"> <div id="toc"> <div id="toc-action-bar"><a href="javascript:;" >Fold</a><a style="display: none" href="javascript:;" >Unfold</a></div> <div class="title">Table of Contents</div> <div id="toc-list"> <div style="margin-left: 2em;"><a href="#toc0">The Economics of Contracts</a></div> <div style="margin-left: 2em;"><a href="#toc1">The Problem With Software Versions</a></div> <div style="margin-left: 2em;"><a href="#toc2">Contract Life-Cycles</a></div> <div style="margin-left: 2em;"><a href="#toc3">Defining Interoperability</a></div> <div style="margin-left: 2em;"><a href="#toc4">The Software Bill of Materials (SBOM)</a></div> <div style="margin-left: 2em;"><a href="#toc5">Long Live Version Numbers!</a></div> <div style="margin-left: 2em;"><a href="#toc6">Worked Example</a></div> <div style="margin-left: 2em;"><a href="#toc7">Conclusions</a></div> </div> </div> </td> </tr> </table> <h2><span>The Economics of Contracts</span></h2> <p>In this section I'll explain why we need contracts and standards in software.</p> <p>Definitions first: a &quot;software contract&quot; is an API, or a protocol, or some other formalized interaction that allows two otherwise unconnected components of a system to work together. I've written a lot about contracts, because they are so vital to making successful distributed software. Contracts let us build overall systems in parallel, in many places and at many times, and with many teams. However, contracts are a vital concept in all types of software.</p> <p>All libraries and products implement contracts, explicit or implicit. Contracts may be documented (using formal prose like RFCs, ideally), or embedded in code (less than ideal). A contract may have multiple independent and competing implementations, and the more implementations, the better.</p> <p>In ZeroMQ we have wire-protocol contracts like the <a href="http://rfc.zeromq.org/spec:23">ZMTP protocol</a> and <a href="http://rfc.zeromq.org/spec:26/CURVEZMQ">CurveZMQ security protocol</a>, and the semantics of various socket patterns. We also have contracts for the API, specified as man pages.</p> <p>When a contract is written and published by third parties, it becomes a standard.</p> <p>The economics of standards are simple: they enable competition between suppliers, and this drives down the cost of products. Suppliers have an incentive to keep contracts undocumented, over-complex, hard to implement, or even proprietary. Customers have an incentive to turn contracts into standards, to simplify them, make them easier to implement, and bring the cost of knowledge to zero.</p> <p>In markets where standards are properly regulated to remain free and open, the cost of goods does fall as it should. In markets where prices are not falling, the cause is generally lack of competition, enabled by closed, complex, or undocumented contracts. Free and open standards promote a competitive free market, whereas captive standards or captive contracts raise costs.</p> <p>This is how it works in large-scale real world economies, and it is also how it works in software projects, which emulate economies (often they emulate an insane centrally planned economy, though <a href="http://hintjens.com/blog:74">that is another story</a>).</p> <p>In any software project, even an open source one, the incentives of competition and capture are present, even if Euros and Dollars aren't literally on the table. We are all Comcast, at times. When you're choosing a software stack, your primary questions should be, &quot;does this stack implement public contracts?&quot; and then, &quot;who else implements these same contracts and are they standards?&quot;</p> <p>A contract needs several properties to work as a real public standard. Above all, it must be published, and it must be freely remixable (to prevent capture). The more we tend to formal processes and organizational ownership, the more it costs to make a contract, and the more vulnerable it is to capture.</p> <p>So ideal public contracts are owned collectively, and published centrally only for convenience. Every project and product must be free to define its own contracts, either new ones, or remixes of existing works. These contracts should move, over time, towards stability and acceptance as standards by the market (if they are successful), or else should die and disappear.</p> <h2><span>The Problem With Software Versions</span></h2> <p>In this section I'll try to nullify the dominant theory of software versions.</p> <p>The worst times in ZeroMQ's history were when we changed the library version to signal major and incompatible change in its contracts. Version 2.0 did not talk to version 3.0, which did not talk to (the then) 4.0. They had incompatible protocols and different APIs. These were in effect different products, each trying to define its own private (and poorly documented) contracts.</p> <p>To fix this problem, we introduced the rule that new stable releases of the software must (a) talk to old stable releases and (b) they must support existing apps, without changes. We more or less succeeded with that, so ZeroMQ versions 3.2 and 4.0 work nicely with 2.2 and 2.1, for example. We slipped only once or twice, by shipping a stable release with new contracts that turned out to have flaws which needed fixing.</p> <p>Initially, this rule made it harder to make stable releases, as the size and reach of the ZeroMQ contracts grew. Yet by moving to a <a href="http://rfc.zeromq.org/spec:22">more organic process</a> we found that our master branch was stable most of the time. Banning breaking changes had the effect of reducing the impact of errors. Fewer large changes means fewer bugs in released code. Today, we make stable releases of core ZeroMQ projects like CZMQ by tagging master.</p> <p>If you look at libzmq (the original &quot;ZeroMQ&quot;), you'll see <a href="https://github.com/zeromq/libzmq/blob/master/include/zmq.h">a single header file</a> that defines the API contract. This is the most significant to most users, since it is what they write code against. If you read that file, you'll see it is rather chaotic and unstructured. It ends in an &quot;undocumented&quot; section marked &quot;use at your own risk&quot;.</p> <p>There is no ZeroMQ &quot;team&quot;. Change to the code base (in all ZeroMQ projects that use our C4.1 process) is driven by a distributed process that collects real world problems from users, prioritizes them, estimates their importance, and then rapidly tests solutions against them until an acceptable solution emerges. The emphasis is on low latency and accuracy.</p> <p>Since change is driven by use, as a product gets wider use, change also hits a wider front. We're not talking deep, dramatic shifts (though <a href="http://hintjens.com/blog:84">some threads</a> may sound like that). Rather, we're talking about tiny evolutionary changes happening in many areas.</p> <p>Change to a system creates shifts in knowledge and costs, resulting in &quot;vertical tipping points&quot;. This is when a series of answers to a whole set of problems can suddenly be recast as a new model, with new abstractions that hide much or all of the complexity that has grown up.</p> <p>For example in ZeroMQ, to make a workable client-server pattern, you take DEALER and ROUTER sockets, configure them in various ways, add heartbeating and sessions and timeouts, and perhaps discovery. We start to see that this pattern happens over and over again. And suddenly we hit a tipping point where it makes sense to design &quot;server&quot; and &quot;client&quot; classes.</p> <p>We accumulate change horizontally, and then we refactor vertically. This is a classic and effective pattern for building software systems. The outcome is, however, that the library is never really stable, and never finished as long as people are using it in new applications.</p> <p>This seems nightmarish, and yet it is not. The trick is to understand two things. First, changes are naturally localized. Even if zmq.h looks like one long contract, it really covers several different areas. And these areas each have their natural cycle through experimentation to stability.</p> <p>Here is the key understanding: <strong>a real product has multiple contracts, that change independently</strong>. Take <a href="http://api.zeromq.org/czmq3-0:_start">CZMQ</a>, which has a better-designed API than libzmq. This library has about 40 classes, each with its own contract.</p> <p>When we claim &quot;version X is stable&quot;, we are claiming either &quot;all contracts in version X are stable&quot;. In the reality of popular products, the only way to guarantee this is to lock all contracts into synchronization, by force.</p> <p>From our experience, we want a decentralized, lock-free development process. That has proven to be the fastest, most accurate, and most enjoyable way to work. This process is incompatible with coercive synchronization of all the contracts in a widely used product. Thus, it is incompatible with software versions.</p> <p>Since every distributor insists on stable versions of code, there are of course answers to this puzzle. One is to reduce the size of products so they do implement only one contract, which can be coerced into stability. We get an explosion of libraries (we'd need 40 to cover CZMQ), and we start to depend on power and force for our work (something that's both distasteful and from experience, unproductive). &quot;You cannot make this patch because we're making a stable release&quot; is a failure, IMHO.</p> <p>Before I explain another answer that does not depend on coercion or fragmentation, let's recap what we really want to achieve (apart from making packagers and Enterprise customers happy):</p> <ul> <li>We want a real-time pipeline connecting our software economy, so problems flow in one direction, and answers in the other. Annual releases just don't cut it. We want real-time, continuous delivery of small, incremental patches.</li> </ul> <ul> <li>We want <strong>guaranteed</strong>, testable backwards compatibility with stable contracts. I'd love to be testing libzmq master against the test cases from older stable releases.</li> </ul> <ul> <li>We want freedom to refactor vertically <strong>at any time</strong> and without upfront coordination. This means creating and delivering (so, testing) new contracts at any time.</li> </ul> <ul> <li>We want a coercion-free process where power is used only to regulate contracts and cheats. This is essential to get scale. Upfront coordination is the mutex of software development.</li> </ul> <p>OK, we probably want a lot more than this, however it's a good list to work with.</p> <h2><span>Contract Life-Cycles</span></h2> <p>The first step to enlightenment is to see that contracts have a life-cycle. This applies to all contracts, both in software and in the real world. The contract life-cycle is not an invention, it's a feature of real world economics, and a useful one for software engineering.</p> <p>Public contracts most definitely change over time. Changes are not always backwards compatible. I cannot plug a horse into the house electricity mains. My 3/4&quot; flat-headed screw does not fit the 1/2&quot; hole in the wall. If I plug a 110V US toaster into my 220V kitchen in Brussels, the toaster dies rapidly and dramatically.</p> <p>Do I care what version the toaster is? No. Do I care what contracts it implements? Most definitely so. These are written in bold on the packaging, and those claims are wrong, I can sue the distributor and manufacturer for fraud.</p> <p>To be of general use, a standards must be stable. Of course there can be variation. I can plug a 220V toaster into a 210V, 220V, 230V, or even a 240V circuit without risk. Standards can have variations, as long as these are compatible with stable versions. This goes one way: we do not usually update shipped products over time, as standards change.</p> <p>How do we know when a contract is stable enough to qualify as a &quot;standard&quot; then? Well, for public contracts (the ones we care about and strive to make), stability is a negotiated peace between users (clients) and suppliers. Change can lower costs, yet can also create costs as the contract affects more points. So eventually the cost/benefit trade-offs drive both sides to agree that change now stops.</p> <p>If you look at the CZMQ classes, you'll see some are marked &quot;deprecated&quot;. If you look at <a href="http://rfc.zeromq.org/">the ZeroMQ RFCs</a>, you'll see more elaborate tagging.</p> <p>The life-cycle of a contract can be obfuscated, by not documenting it. Let's assume our contracts are written down, not embedded in the software somewhere.</p> <p>A new contract usually has no implementations. Until someone signs a contract (demonstrates it in code), it's just speculation. I call these &quot;raw&quot; contracts. Since no-one is using a raw contract, and it's usually incomplete and immature, it changes a lot, without hurting anyone.</p> <p>When you can demonstrate a contract in code, it gets some status. I call these &quot;draft&quot; contracts. A draft contract will change a lot, often in tandem with its implementation. This is fine, and hurts no-one.</p> <p>When two or more parties implement a contract, and especially when there are third parties depending on the contract, however, things get serious. I call these &quot;stable&quot; contracts. Change to stable contracts needs upfront agreement. You cannot rely on this, except in young stable contracts with few users.</p> <p>Eventually a stable contract gets replaced by new draft contracts. I call these &quot;legacy&quot; contracts. Changing legacy contracts is just an all-round bad idea. Finally, when new stable contracts emerge, the old ones become &quot;retired&quot;.</p> <p>Sometimes, new stable versions of a contract can talk to older legacy versions. Alternatively, software may implement both older and new versions of a contract.</p> <p>There are three key points here:</p> <ul> <li>A realistic software system will implement many contracts, rather than just a single one. Whether or not these contracts are documented, a successful software system will, over time, add more and more contracts to the set it implements.</li> <li>Each of these contracts goes through a draft-stable-legacy-retired life-cycle, which can be less or more formally defined.</li> <li>While the life cycles of the different contracts may drive each other, they are naturally independent. To force all contracts in a system to the same state requires significant coercion and cost.</li> </ul> <p>Hopefully you see why trying to force an entire product into one state does not scale well.</p> <h2><span>Defining Interoperability</span></h2> <p>Interoperability is the ability of products X and Y to work together. My WiFi router has a list of USB 3G modems it works with. This seems good, right? Actually, no, it's a rubbish approach. It's like saying, &quot;this toaster is compatible with versions 3.1 and later of my home&quot;.</p> <p>To define interoperability as a relationship between products is to assume that the set of products is limited and testable, and exists only within a given time and space. Yet real systems stretch over space and time. When I build a house, I equip it slowly, over years. The process of improving it never stops. The only way I can get the right toasters at the right price is to search widely and slowly (i.e. over space and time).</p> <p>It's far better to say, &quot;my house has a 16A 220V-50Hz electric circuit&quot; and &quot;this toaster draws 4A at 220V-50Hz&quot;. That is, to define an electricity contract, and then define interoperability as &quot;respects this contract&quot;. The supply of toasters that implement that contract is huge. The supply of toasters that implement House V3.1 is small, if not tiny to the point of &quot;only a Russian billionaire would consider this.&quot;</p> <p>A list of &quot;compatible devices&quot; is a red flag that tells us, &quot;this area is not standardized and thus you can expect to pay many times what you should.&quot;</p> <p>Ditto for software. When you install a software product you are making a long term investment. The accounting of that decision depends on the contracts the software respects. It is interesting to know what's inside the software, for sure. Is it fast, does it crash often, can it handle many users? However it's far more interesting to know what standards it implements, and how well.</p> <p>Software systems <a href="http://en.wikipedia.org/wiki/Systemd">that do not respect and promote public contracts</a> create a sense of unease and disquiet. It does not really matter whether they're open source or not. Technically and economically, the alternative to an architecture based on contracts is one based on coercion.</p> <p>I believe that in removing the concept of software versions, and focusing instead on the contracts that a system implements, we can get a more accurate description of what we are getting, as consumers. Further, it's a description that is mechanically testable, and could even be held up as a legally binding statement by software producers.</p> <h2><span>The Software Bill of Materials (SBOM)</span></h2> <p>Let me introduce the Software Bill of Materials, or SBOM. The SBOM is a testable statement of the contracts (e.g. RFCs) that a software product implements. The SBOM is a claim of backwards and forwards interoperability with other products, based those product's own SBOMs, rather than product version numbers.</p> <p>To implement an SBOM, a software project has a section in its README that says, for instance:</p> <div class="code"> <pre><code>## Software Bill of Materials This software implements the following public contracts: * project/contract/name/state * ...</code></pre></div> <p>If an implementation supports several versions of a contract, it should list them all. Thus libzmq, for example, implements ZeroMQ RFCs 13, 15, and 23 (three versions of ZMTP).</p> <p>This may seem optimistic, yet the goal should be that the SBOM defines *fully* the behavior of the software system as far as it affects other software. As in any product, there will be design trade-offs, e.g. performance vs. resource consumption. If these are relevant to the outside world, they should be defined as public contracts.</p> <p>The SBOM depends on a very cheap, fast way to develop RFCs through their life-cycle. I developed and tested this starting with the <a href="http://digistan.org">Digital Standards Organization</a> (Digistan) in 2005, and then with ZeroMQ RFCs up to the present day.</p> <p>An RFC is simply a contract that's published on a public platform. Under the Digistan rules, such documents use the GPLv3 license, so can be freely forked and improved. This solves the problem of capture (&quot;No, I won't improve my RFC to make it easier for you to implement&quot;).</p> <p>We've additionally been using man pages as contracts for APIs, and this works up to a point. Both libzmq and CZMQ as well as other projects do this. It is however too easy to change the contract together with the software, and break existing applications.</p> <h2><span>Long Live Version Numbers!</span></h2> <p>In ZeroMQ we still use version numbers for two main reasons:</p> <ul> <li>We don't have fully testable or tested contracts, and so code on master still has faults that emerge over time. We reduce the risk by forking master to a separate repository and slowly fixing this, without taking new functionality from master. This emerges as major.minor.patch.</li> </ul> <ul> <li>Version numbers are powerful tools for marketing, and especially for replacing old rubbish with new, exciting, rubbish.</li> </ul> <ul> <li>If (if!) we remove support for retired contracts, the version number would make this clear. &quot;Version X no longer supports the frongle interface.&quot;</li> </ul> <p>We can still provide version numbers by tracking the SBOM. I'd simply number the SBOM changes from 1 upwards, unless we find we need more detail. Perhaps the repository commit number within the SBOM number.</p> <h2><span>Worked Example</span></h2> <p>Since I like to eat my own cooking, I'm going to start using the SBOM approach for CZMQ, and if it works there, spread it to other projects. CZMQ implements a variety of ZeroMQ RFCs, and its own API contracts.</p> <p>From experience we know that a single CZMQ class can contain multiple contracts, each with its own state. E.g. zsys contains draft methods, stable methods, and retired methods. I'll to tag these API contracts as &quot;draft&quot;, &quot;stable&quot;, &quot;legacy&quot;, or &quot;retired&quot;. Further, when we change contracts (draft and stable, probably) we'll number those changes.</p> <p>So the SBOM for CZMQ might contain entries like this:</p> <div class="code"> <pre><code>* czmq/zsys/udp.1/stable * czmq/zsys/presets.1/stable * czmq/zsys/interrupt.1/retired * czmq/zsys/interrupt.2/stable * zeromq/RFC/4/stable</code></pre></div> <p>Where each entry in the SBOM matches a test case living either in CZMQ, or (ideally elsewhere). Incidentally, moving the tests out of the project solves the common question with contract driven development: &quot;what if someone breaks a contract and then modifies the test case to hide that break?&quot;</p> <h2><span>Conclusions</span></h2> <p>As I've explained, a living software product will usually deliver a mix of draft, stable, legacy, and retired contracts. Rather than try to assign a &quot;major.minor.patch&quot; version number to the overall mix, to indicate stability and maturity, it is more sensible to list the contracts explicitly in the living code (on git master).</p> <p>Implementations of draft contracts carry no promise of interoperability. It is fair to assume that the market for draft contracts is small, and the cost of change is low. Implementations of stable contracts are guaranteed to work with all other implementations of the same stable contract. A stable contract should be testable, and the claim of a vendor to implement it could be legally binding.</p> <p>By listing all contracts that a software project implements as a &quot;Software Bill of Materials&quot;, or SBOM, we make it possible to test every single master commit against these contracts. While today we tend to run CI tests within a single project, it would be better to have external test suites, one per contract. Since people will demand version numbers of some sort, we can version the SBOM, and commits within that. So version 12.122 of a product will be SBOM version 12, commit #122.</p> <p>As a worked example, I will experiment with <a href="http://czmq.zeromq.org">CZMQ</a>, one of the projects I'm mainly responsible for.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:84</guid>
				<title>Revisting ZeroMQ Multipart</title>
				<link>http://hintjens.wikidot.com/blog:84</link>
				<description>

&lt;p&gt;Around FOSDEM 2015, a few core ZeroMQ maintainers decided to experiment with a simpler messaging API, and decided it&#039;d be profitable to explore rethinking multipart messages from ZeroMQ. In this article I&#039;ll explain the why&#039;s and how&#039;s of this potential shift.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 03 Feb 2015 09:57:33 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Around FOSDEM 2015, a few core ZeroMQ maintainers decided to experiment with a simpler messaging API, and decided it'd be profitable to explore rethinking multipart messages from ZeroMQ. In this article I'll explain the why's and how's of this potential shift.</p> <table style="margin:0; padding:0"> <tr> <td style="margin:0; padding:0"> <div id="toc"> <div id="toc-action-bar"><a href="javascript:;" >Fold</a><a style="display: none" href="javascript:;" >Unfold</a></div> <div class="title">Table of Contents</div> <div id="toc-list"> <div style="margin-left: 2em;"><a href="#toc0">Don't Panic</a></div> <div style="margin-left: 2em;"><a href="#toc1">What's the Problem?</a></div> <div style="margin-left: 2em;"><a href="#toc2">The Identity Problem</a></div> <div style="margin-left: 2em;"><a href="#toc3">The Multihop Fallacy</a></div> <div style="margin-left: 2em;"><a href="#toc4">A Better Framing Approach</a></div> <div style="margin-left: 2em;"><a href="#toc5">A Better Client-Server Pattern</a></div> <div style="margin-left: 2em;"><a href="#toc6">Heartbeating and Sessions</a></div> <div style="margin-left: 2em;"><a href="#toc7">Why Threadsafe Sockets?</a></div> <div style="margin-left: 2em;"><a href="#toc8">CZMQ Changes</a></div> <div style="margin-left: 2em;"><a href="#toc9">How This Would Happen</a></div> <div style="margin-left: 2em;"><a href="#toc10">Conclusions</a></div> </div> </div> </td> </tr> </table> <h2><span>Don't Panic</span></h2> <p>We don't remove functionality that people are using. The existing multipart functionality is defined by ZeroMQ RFCs 23 (ZMTP) and 28 (the request-reply pattern). There is no plan to stop supporting these RFCs, nor to remove the multipart API contracts. Our strategy for shifting ZeroMQ's functionality is to develop new contracts over time, and when these are stable and proven, deprecate old ones. This happens over many years, with new code existing in parallel to old code.</p> <p>So the focus of this experiment are mainly in new code: new language bindings, new protocols, and new stacks. The overall goal, as I'll explain, is to make things simpler, and easier to understand.</p> <h2><span>What's the Problem?</span></h2> <p>Multipart messages aim to solve a number of problems, and in turn create a number of problems. At the core of our shift is the understanding that the costs now appear to outweigh the benefits.</p> <p>First, let's collect the problems that multipart solves:</p> <ul> <li>It allows zero-copy for high-volume pub-sub data, where the application sends a routing key, followed by a body. With one part, the body must be copied into a buffer. With two parts, the body can be sent directly from an existing buffer (thus, no copying).</li> </ul> <ul> <li>It provides a mechanism for multi-hop request-reply, where routing identifiers are pushed to an &quot;envelope&quot;, and popped on the return path.</li> </ul> <ul> <li>It provides applications with a simple serialization mechanism, either to avoid using additional libraries, or so that brokers can add and remove information to messages they are forwarding.</li> </ul> <p>Now, let's list the main problems that we've seen with the multipart model in ZeroMQ:</p> <ul> <li>It is confusing, as a &quot;message&quot; means both a part, and a list of parts. We've had to add new terms like &quot;frame&quot; to compensate.</li> </ul> <ul> <li>The multipart request-reply envelope is complex to understand, and yet any realistic application has to use it. This creates a real learning cost.</li> </ul> <ul> <li>ZeroMQ servers exploit the request-reply envelope to do server-client routing (using ROUTER sockets). This always confuses new users.</li> </ul> <ul> <li>ZeroMQ implementations cannot realistically make sockets threadsafe, as they must serialize multiple send and recv calls to a single thread. Thus, multipart messages have stopped us making threadsafe sockets.</li> </ul> <ul> <li>Multipart messages are counter-intuitive; the &quot;send&quot; method does not actually send anything; it queues the message until the final part is sent. New users often try to use multipart to send large files. This does not work.</li> </ul> <ul> <li>The two main sockets that exploit the multipart mechanism (REQ and REP) cannot recover from failures, and rarely used by real applications.</li> </ul> <ul> <li>Supporting multipart messages has raised complexity and performance in all bindings and tools. It is significantly harder and more work to support a list of messages than to support a single frame.</li> </ul> <ul> <li>Multipart data is incompatible with other layers that treat data as a stream of bytes or blobs. For example, the Go I/O interface expects a transport to read and write blobs.</li> </ul> <h2><span>The Identity Problem</span></h2> <p>The ZMQ_IDENTITY socket setting is one of the more confused, and in my view dangerous, semantics in ZeroMQ. It allows a DEALER/REQ/REP peer to tell a ROUTER socket what value to use for its internal routing ID. &quot;User-defined identities&quot; arrive as a magical first frame that can be up to 255 bytes long.</p> <p>It was a mistake to mix node identities with routing information. These are two separate layers (contracts) and mixing them creates a confused hybrid contract. What happens when two clients connect with the same identity? At what stage is the identity checked? How do we correlate such identities with application-level identities? How do we proxying traffic?</p> <p>It has been clear for some time that:</p> <ul> <li>We should stop using the term &quot;identity&quot; for server-side routing information (which is essentially the handle of a pipe).</li> <li>We should delegate identity management (authentication and access control) to higher layers, where different decisions can be made depending on the case.</li> <li>We should in fact hide the routing information in simple request-reply servers.</li> </ul> <h2><span>The Multihop Fallacy</span></h2> <p>The multipart request-reply envelope solves what appears to be a fallacy, a fake problem. That is: we want to be able to carry a single message across many hops, from originator to recipient, and then carry a reply back along the same path.</p> <p>This scenario does not seem to happen in practice. There is a very good reason for this, stemming from the essential need of a distributed system to work in layers, and hide the internals of every layer from other layers.</p> <p>Put this another way, the extended request-reply scenario assumes, or tries to enforce, a single contract that spans across many layers. And this is a failing pattern. Success needs specific contracts between each layer, and the flexibility to change these at need, without affecting other layers.</p> <p>Take an example, the Majordomo protocol that takes client work requests, and delivers them to workers. This is practically the simplest kind of load balancing we can do.</p> <p>In Majordomo we have two contracts. One defines the interaction between clients and the broker. The second defines the interaction between workers and the broker. These two layers are separate, and it is profitable to keep them so. It lets us evolve the worker contract (adding heartbeating, timeouts, recovery) and the client contract (e.g. adding scheduling and quotas) separately. It lets us experiment with multiple worker-broker contracts without affecting client applications.</p> <p>Clearly we do carry payloads across both layers. However there is an intelligent piece of code switching between the two layers, and translating messages from one contract to another.</p> <p>So it looks like multihop request-reply can be falsified as a theory, and thus the use case for request-reply envelopes can also be falsified.</p> <h2><span>A Better Framing Approach</span></h2> <p>In the last few years the ZeroMQ community has developed its own tool for framing, namely <a href="https://github.com/zeromq/zproto">zproto</a>. This generates a fast binary codec for a protocol, in arbitrary languages (Go, Clojure, Java, C, C# at this stage).</p> <p>The advantage of zproto over framing is that you get a properly documented protocol with robust error checking at client and server side. For example, ZeroMQ RFC 7 (the Majordomo protocol), uses multipart framing for its protocol, which makes it expensive to implement the protocol, or evolve and improve it.</p> <h2><span>A Better Client-Server Pattern</span></h2> <p>While the standard pattern for client-server cases is DEALER-ROUTER, these sockets are clumsy and often confusing to newcomers. Their names are unclear. The ROUTER socket uses multipart messages for routing, which is semantically and technically confusing.</p> <p>There is a much simpler, more obvious client-server pattern:</p> <ul> <li>CLIENT and SERVER socket types that are separate from the request-reply pattern.</li> <li>CLIENT can implement, immediately, necessary logic for heartbeating, and recovery from server restarts.</li> <li>SERVER can implement client sessions, recovery from network failures, and disconnection of idle clients.</li> </ul> <p>There are several possibilities for a SERVER socket design:</p> <ul> <li>Just like ROUTER today, except the routing information is not provided as a multipart frame. Instead, it is a message property (it cannot be a socket property, if sockets are to be threadsafe).</li> </ul> <ul> <li>A higher level socket that automatically manages client sessions. This means, identifying new connections and re-connections (when the same client reconnects on a different network socket), responding to heartbeats, and expiring idle clients. The API here would add a &quot;session&quot; object, corresponding to a single client session.</li> </ul> <p>Similarly, CLIENT could be very similar to DEALER, or something more sophisticated that deals with the requirements we always have in client-server scenarios.</p> <h2><span>Heartbeating and Sessions</span></h2> <p>Looking at several years of building client-server stacks with ZeroMQ, a consistent pattern emerges for reliable session management. We build this today using DEALER-ROUTER and zproto for protocol commands. It could profitably be built into the CLIENT-SERVER sockets, and the ZMTP protocol:</p> <ul> <li>The server must detect new client sessions. Ideally, a session identifies a CLIENT socket instance, with the same lifecycle. Today we use the routing ID, which means we cannot recover a client session after a network break.</li> <li>The client must send heartbeats, when idle. The heartbeat interval is typically one or several seconds, depending on client-side power considerations. A heartbeat command (&quot;PING&quot;) carries no data.</li> <li>The server must repond to heartbeats, simply by sending a heartbeat reply (&quot;PING-OK&quot;), again carrying no data.</li> <li>Clients must send at most a few PINGs, if they are not getting PING-OK replies. Otherwise they will fill up their outgoing pipes with a thousand PING commands.</li> <li>Servers must expire clients that have sent nothing within a certain timeout (typically 10 to 30 seconds, depending on the network).</li> </ul> <p>For session management, the client must send a unique ID that can be used as session ID. Today we use the routing ID for this. Some applications use the ZMQ_IDENTITY setting for this. Neither are ideal. The best solution is that a CLIENT socket automatically generate its own unique session ID, which cannot be over-ridden or used at any layer except this one.</p> <p>The client sends its session ID when connecting to the server. The server holds known client sessions in a table. If the client connects with an existing session ID, the server attaches that new connection to the existing session. If not, it creates a new session. Sessions expire when they have no activity for 10-30 seconds (per heartbeating).</p> <p>This session reconnection is invisible to the application. It sees, at worst, a brief lull in traffic, which then resumes.</p> <p>Separately, the SERVER socket provides a routing ID for each message. This is an internal short integer that identifies the session. The SERVER does NOT expose the session ID. If applications want their own client identifiers, they build these themselves.</p> <p>The SERVER's routing ID is a socket (and perhaps also message) property that the caller can get (after receiving a message) and set (before sending a message). It is trivial to write simple servers, which can just be a recv/send loop, like today's REP sockets. Unlike REP sockets, a SERVER socket has no state machine and can trivially recover from errors.</p> <h2><span>Why Threadsafe Sockets?</span></h2> <p>One of the unexpected costs of multipart messages was that sockets could not be threadsafe. It's obvious why: a socket has to serialize an unknown number of &quot;send&quot; commands from a single caller thread. If receiving and sending is an atomic operation, the socket can be threadsafe, else not.</p> <p>Threadsafe sockets resolve a major, long-standing problem, of using ZeroMQ from languages that spawn many threads. This is such a common use case: the UI spawns a thread which wants to send a message. Today it must create a new socket, connect it, send its message, and destroy the socket. This is not fast.</p> <p>Ideally, the new thread would grab the socket from shared memory, send to it, and die happily. Note that this is for a one-way message flow. If threads need a reply from their socket, they must use (today) a DEALER-ROUTER model, and (in our new model) a CLIENT-SERVER model.</p> <p>There have been abortive attempts to make ZeroMQ sockets threadsafe. They did not, however, make the codebase simpler. Removing multipart messages (even if this is a compile time option), makes threadsafe sockets possible.</p> <h2><span>CZMQ Changes</span></h2> <p>As a worked example, let's see how this could change the CZMQ API:</p> <ul> <li>Deprecation of the zmsg and zframe classes, and promotion of zchunk (or byte * + size_t) as the basic message type.</li> <li>New zclient and zserver classes, which implement CLIENT and SERVER sockets, as described above. Initially these could be emulated over DEALER and ROUTER, later over real CLIENT and SERVER.</li> <li>Deprecation of all functionality that supports identities and multipart.</li> <li>A new &quot;reply&quot; semantic, for SERVER sockets, which replies to a previously received message. This can be implicit (reply to socket), if the socket is thread local, or explicit (reply to message or to message routing id) if the socket is shared between multiple threads.</li> <li>Change of actors and pipes to use CLIENT-SERVER instead of PAIR-PAIR. This lets actors reply to caller requests, where each caller would get its own client socket to speak to the actor.</li> </ul> <h2><span>How This Would Happen</span></h2> <p>Clearly some of the goals we have — simplifying the internals of ZeroMQ stacks — are not compatible with existing applications.</p> <p>We cannot break existing application code, and so future ZeroMQ stacks will need to continue supporting multipart data. Some options for doing this are:</p> <ul> <li>To build a new socket types (client, server) that are threadsafe and that work on single parts only. This would leave the existing codebases largely untouched.</li> <li>To fork the codebase. Not perhaps the nicest option.</li> <li>To support both models, and allow newer applications to disable multipart, to get the eventual advantages.</li> </ul> <h2><span>Conclusions</span></h2> <p>It's unclear we can make these shifts successfully. However, if we can, then here are some potential outcomes:</p> <ul> <li>The REQ-REP-DEALER-ROUTER socket types will disappear (be deprecated).</li> <li>The ZMQ_IDENTITY concept will disappear.</li> <li>New CLIENT and SERVER sockets will replace REQ-REP-DEALER-ROUTER.</li> <li>Messages will be single opaque blobs of data.</li> <li>All other names for messages (frames and parts) will be deprecated.</li> <li>All &quot;recv more&quot; and &quot;send more&quot; semantics will be deprecated.</li> <li>CLIENTs and SERVERs may eventually do heartbeating and session management automatically.</li> <li>All socket types that no longer accept multipart messages can probably be made thread safe.</li> </ul> <p>Comments and discussion welcome, please use zeromq-dev for this.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:79</guid>
				<title>Solving the Makefile Problem</title>
				<link>http://hintjens.wikidot.com/blog:79</link>
				<description>

&lt;p&gt;The ZeroMQ community started many years ago as a group of low-latency fanatics who focused their &amp;quot;make it cheaper to build distributed systems&amp;quot; mission on a single library, libzmq. The mission hasn&#039;t changed, yet the focus is wider than ever. In this article I will talk about a young project, &lt;a href=&quot;https://github.com/zeromq/zproject&quot;&gt;zproject&lt;/a&gt;, which makes it cheaper to build other projects that use ZeroMQ.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 14 Nov 2014 11:16:13 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>The ZeroMQ community started many years ago as a group of low-latency fanatics who focused their &quot;make it cheaper to build distributed systems&quot; mission on a single library, libzmq. The mission hasn't changed, yet the focus is wider than ever. In this article I will talk about a young project, <a href="https://github.com/zeromq/zproject">zproject</a>, which makes it cheaper to build other projects that use ZeroMQ.</p> <h2><span>Pause, Rewind, Play</span></h2> <p>In 1999 I wrote an article for Dr. Dobb's Journal on &quot;Template Based Code Generation&quot;. The <a href="http://legacy.imatix.com/pub/info/codegen.pdf">PDF whitepaper</a> says, &quot;Template-based code generation is a powerful way to reduce the cost and effort of writing code. It's a technique that's underused by most developers, because there is little literature on this subject, and there are few decent code generation tools.&quot;</p> <p>In 1999 I'd already been writing and using template based code generators for 15 years. Jonathan Schultz and I worked for about ten years to refine these techniques, ending in 2005 or so with GSL v4, which we used heavily to build <a href="http://www.openamq.org">the OpenAMQ messaging system</a> (the first, and the fastest, AMQP server and client).</p> <p>OpenAMQ taught us a few things, not all happy lessons. One lesson was especially harsh: <strong>meta hurts</strong>. In 2005 we abandoned our entire technology stack, code generators and all, believing the world was not ready for it, and never would be. When we started building ZeroMQ, it was in C++ (ugh) and by hand, with zero code generation (oh god why?!). We chucked GSL into hibernation and I stopped coding for a while, it was too painful to step back so far into the past.</p> <p>It seemed, for years, that no-one understood the power and beauty of code generation. It was too different from the industry standard perception of how we make and value code. Code was, and mostly still is, seen as an asset rather than a liability. The truth is that in software design, as in any domain, <em>all that matters are our models</em>. Good models are simple, abstract, accurate, and tethered to reality. Bad models are fuzzy, complex, and based on falsehoods.</p> <p>Here is a bad model: &quot;Freedom is about having more flavors of ice-cream.&quot; Here is a good model: &quot;Freedom is about doing interesting things with other people.&quot; The difference should be immediately obvious. If you're confused here, you need to review your priorities in life. A bad model confuses and traps us. A good model empowers us.</p> <p>Code generation isn't about replacing the hapless coder with a robot. It's about teaching that coder to build models instead of code, to think in terms of simple, clean, accurate abstractions. That is, to learn to develop simple domain specific languages, with the tools to design and test and implement them cheaply and rapidly.</p> <p>I used to call this <a href="http://download.imatix.com/mop/">&quot;Model Oriented Programming&quot;</a>, before shutting down our code generation machines and focusing instead on social architecture, aka <em>&quot;messing with people on a large scale, for their own benefit of course, cause otherwise that'd be Machiavellian and anti-social and even oh noes very profitable.&quot;</em></p> <p>Well, <a href="https://github.com/sustrik/ribosome">code generation seems to be in fashion</a>. Yay! Finally. GSL — the original and the best — found <a href="https://github.com/imatix/gsl">a new home on GitHub</a>.</p> <p>I'm happy to say that a slice of the ZeroMQ community has embraced model oriented code generation with a passion. About seven months ago I announced <a href="http://hintjens.com/blog:75">zproto</a>, a tool for generating ZeroMQ servers, and clients.</p> <p>While I like zproto and use it every day, the more interesting tool, because it solves far more horrid problems, is <a href="https://github.com/zeromq/zproject">zproject</a>.</p> <p>Both zproto and zproject are reboots of old tools from the OpenAMQ toolkit (<a href="http://www.openamq.org/doc:tech-asl">ASL</a> and <a href="https://github.com/imatix/openamq/tree/master/tooling/base2/boom3">Boom</a>, if you care, which you don't, as we both know :)</p> <p>Since I've already talked about zproto, let me explain zproject.</p> <h2><span>The Problem with Makefiles</span></h2> <p>Once, long ago, a smart young person invented Make. He (for even in those days the technical edge of our field was very gender biased) had a chance to save the world. Or at least make it a much better place. Instead, he declared (according to the friend of a friend), &quot;I realize the Makefile syntax is horrid, yet I already have seven users, so changing it is impossible!&quot;</p> <p>The rest is history. Every system has its own way of compiling and linking code. It's such fun to write a new project makefile specification that companies make one every year or two. Microsoft — for once I'm not joking when I mention their name — has different formats for Visual Studio 2008, 2010, 2012, and 2013.</p> <p>Worse, the abstraction is largely useless. Sure, compiling and linking is one thing we want to do. However we also want to generate documentation. We want to build test frameworks, and run them each time the code changes. We want to target arbitrary platforms, today and in the future. We want to wrap our precious C APIs in other languages. We want to do endless things with our project, and above all, escape the limits and conditions set by our tool vendors.</p> <p>This isn't hard to do. It just demands a higher level of abstraction.</p> <p>Here is another good model:</p> <div class="code"> <pre><code>&lt;project name = &quot;zyre&quot; description = &quot;an open-source framework for proximity-based P2P apps&quot; script = &quot;zproject.gsl&quot; &gt; &lt;include filename = &quot;license.xml&quot; /&gt; &lt;version major = &quot;1&quot; minor = &quot;1&quot; patch = &quot;0&quot; /&gt; &lt;use project = &quot;czmq&quot; /&gt; &lt;class name = &quot;zyre&quot; /&gt; &lt;class name = &quot;zyre_event&quot; /&gt; &lt;class name = &quot;zre_msg&quot; /&gt; &lt;class name = &quot;zyre_peer&quot; private = &quot;1&quot; /&gt; &lt;class name = &quot;zyre_group&quot; private = &quot;1&quot; /&gt; &lt;class name = &quot;zyre_node&quot; private = &quot;1&quot; /&gt; &lt;model name = &quot;zre_msg&quot; /&gt; &lt;/project&gt;</code></pre></div> <p>And here is a bad model for the same knowledge:</p> <div class="code"> <pre><code>AC_PREREQ(2.61) AC_INIT([zyre],[m4_esyscmd([./version.sh zyre])],[zeromq-dev@lists.zeromq.org]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AC_CONFIG_HEADERS([src/platform.h]) AM_INIT_AUTOMAKE([subdir-objects tar-ustar foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) PV_MAJOR=`echo $PACKAGE_VERSION | cut -d . -f 1` PV_MINOR=`echo $PACKAGE_VERSION | cut -d . -f 2` PV_PATCH=`echo $PACKAGE_VERSION | cut -d . -f 3` AC_DEFINE_UNQUOTED([PACKAGE_VERSION_MAJOR],[$PV_MAJOR], [ZYRE major version]) AC_DEFINE_UNQUOTED([PACKAGE_VERSION_MINOR],[$PV_MINOR], [ZYRE minor version]) AC_DEFINE_UNQUOTED([PACKAGE_VERSION_PATCH],[$PV_PATCH], [ZYRE patchlevel]) AC_SUBST(PACKAGE_VERSION) LTVER=&quot;2:0:1&quot; AC_SUBST(LTVER) ZYRE_ORIG_CFLAGS=&quot;${CFLAGS:-none}&quot; AC_PROG_CC AC_PROG_CC_C99 AM_PROG_CC_C_O AC_LIBTOOL_WIN32_DLL AC_PROG_LIBTOOL AC_PROG_SED AC_PROG_AWK PKG_PROG_PKG_CONFIG ...</code></pre></div> <p>Which goes on forever, or 262 lines, whichever comes first. Learning autoconf is about as much fun as falling off your kick bike and smashing your face on cheap concrete pavement. Actually, having done both, I prefer the latter. Not that the alternatives are better. CMake, you say? Yeah, CMake is like smashing your face on high quality pavement. You can admire the stonework while the blood pours down your face.</p> <p>Here's the equivalent CMakeLists.txt (again I truncate to reduce your empathic pain):</p> <div class="code"> <pre><code>cmake_minimum_required(VERSION 2.8) project(zyre) enable_language(C) enable_testing() set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) foreach(which MAJOR MINOR PATCH) file(STRINGS &quot;${SOURCE_DIR}/include/zyre.h&quot; ZYRE_blah blah string(REGEX MATCH &quot;#define ZYRE_VERSION_${which} ([0-9_]+) blah if (NOT ZYRE_REGEX_MATCH) message(FATAL_ERROR &quot;failed to parse ZYRE_VERSION_ blah blah endif() set(ZYRE_${which}_VERSION ${CMAKE_MATCH_1}) endforeach(which) set(ZYRE_VERSION ${ZYRE_MAJOR_VERSION}.${ZYRE_MINOR_VERSION}. blah include(CheckIncludeFile) CHECK_INCLUDE_FILE(&quot;linux/wireless.h&quot; HAVE_LINUX_WIRELESS_H) CHECK_INCLUDE_FILE(&quot;net/if_media.h&quot; HAVE_NET_IF_MEDIA_H) include(CheckFunctionExists) CHECK_FUNCTION_EXISTS(&quot;getifaddrs&quot; HAVE_GETIFADDRS) CHECK_FUNCTION_EXISTS(&quot;freeifaddrs&quot; HAVE_FREEIFADDRS) include(CheckIncludeFiles) check_include_files(&quot;sys/socket.h;net/if.h&quot; HAVE_NET_IF_H) if (NOT HAVE_NET_IF_H) CHECK_INCLUDE_FILE(&quot;net/if.h&quot; HAVE_NET_IF_H) endif() file(WRITE ${BINARY_DIR}/platform.h.in &quot; #cmakedefine HAVE_LINUX_WIRELESS_H #cmakedefine HAVE_NET_IF_H #cmakedefine HAVE_NET_IF_MEDIA_H #cmakedefine HAVE_GETIFADDRS #cmakedefine HAVE_FREEIFADDRS &quot;) configure_file(${BINARY_DIR}/platform.h.in ${BINARY_DIR}/platform.h)</code></pre></div> <p>Sorry, I removed some blank lines that were loitering around to pretend that is a &quot;language&quot; instead of a slowly rotting heap of fish heads and unwanted celery sticks. Did I see some bits of Perl 3.x in there? I'm sure some people write really pretty CMake scripts. Meh.</p> <p>I've expressed my abundant affection for autoconf and CMake, which leaves about ten other random make systems to mock. Let me summarize my experience: all make systems are rubbish, and some are worse than others.</p> <p>There's a book I want to write, on how to use C properly. By &quot;properly&quot; I mean as we do in CZMQ and Zyre and our other C projects. Actors, classes, neat abstractions for concurrency, and APIs, and useful packages of functionality, that are obvious and trouble-free and accurate, and properly anchored to reality. Perhaps this will be &quot;Code Connected Volume 2&quot; or perhaps a book on &quot;Scalable C&quot;.</p> <p>Anyhow, before zproject, I would have to spend a full chapter (don't mock it, one chapter is equal to fifteen Imperial weekends) simply explaining how to write a Makefile, or autoconf voodoo. What use are elegantly crafted examples if your readers cannot build and run them?</p> <p>With zproject, we are starting to develop that abstraction and test it with real cases. zproject takes a project model, and turns it into makefiles and project files for MSVC (four flavors), Android, MinGW, QT, autoconf, Travis CI, and CMake. It generates a full project skeleton (in C) and maintains this for you as you add and remove classes in your project. It calls code generators, and builds man pages. It even builds bindings for your C libraries, in QML, and soon Ruby and other languages.</p> <p>And we started zproject less than a month ago, on 20 October 2014. Kevin Sapper, Joe Eli McIlvain and Phillip E. Mienk have done most of the heavy work. It started out as part of CZMQ, then grew an independent life.</p> <h2><span>Using zproject</span></h2> <p>To use zproject, fork and clone <a href="https://github.com/zeromq/zproject">the GitHub repo</a>, then read the README. You will need to build and install <a href="https://github.com/imatix/gsl">GSL v4</a>. You don't need to learn GSL to use zproject, though if you want to contribute, you do.</p> <p>zproject is a community project, like most ZeroMQ projects, built using the C4.1 process, and licensed under MPL v2. It solves the Makefile problem really well. It is unashamedly for C, and more pointedly, for that modern C dialect we call <a href="http://rfc.zeromq.org/spec:21">CLASS</a>. CLASS is the Minecraft of C: fun, easy, playful, mind-opening, and social.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:75</guid>
				<title>Generating Servers with zproto</title>
				<link>http://hintjens.wikidot.com/blog:75</link>
				<description>

&lt;p&gt;While ZeroMQ gives you a powerful communications engine to use in many different ways, building a conventional server is still fairly solid work. We use the ROUTER socket for that, managing the state for each individual client connection. Today I&#039;ll present a new tool — &lt;a href=&quot;https://github.com/zeromq/zproto&quot;&gt;zproto&lt;/a&gt; — that generates whole servers, in C, from state machine models.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 29 Mar 2014 13:12:04 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>While ZeroMQ gives you a powerful communications engine to use in many different ways, building a conventional server is still fairly solid work. We use the ROUTER socket for that, managing the state for each individual client connection. Today I'll present a new tool — <a href="https://github.com/zeromq/zproto">zproto</a> — that generates whole servers, in C, from state machine models.</p> <h2><span>Quick Background to zproto</span></h2> <p>zproto is based on work I did for Chapter 7 of the ZeroMQ book, used in FileMQ, Zyre, and several other projects. It's a collection of code generation tools that take models and turn them into perfect code.</p> <p>iMatix used to do code generation as our main business. We got&#8230; very good at it. There are lots of ways to generate code, and the most powerful and sophisticated code generator ever built by mankind lives on Github.com at <a href="https://github.com/imatix/gsl">imatix/gsl</a>. It's an interpreter for programs that eat models (self-describing documents) and spew out text of any shape and form.</p> <p>The only problem with sophisticated magic like GSL is that it quickly excludes other people. So in ZeroMQ I've been very careful to not do a lot of code generation, only opening that mysterious black box when there was real need.</p> <p>The first case was in CZMQ, to generate the classes for ZeroMQ socket options. Then in CZMQ, to <a href="https://github.com/zeromq/czmq/tree/master/model">generate project files</a> (for various build systems) from <a href="https://github.com/zeromq/czmq/blob/master/model/project.xml">a single project.xml</a> file. Yes, we still use XML models. It's actually a good use case for simple schema-free XML.</p> <p>Then I started generating binary codecs for protocols, <a href="https://github.com/zeromq/filemq/blob/master/model/fmq_msg.xml">starting with FILEMQ</a>. We used these codecs for a few different projects and they started to be quite solid. Something like a protobufs for ZeroMQ. You can see that the generated code <a href="https://github.com/zeromq/filemq/blob/master/include/fmq_msg.h">looks as good</a> as hand-written code. It's actually better: <a href="https://github.com/zeromq/filemq/blob/master/src/fmq_msg.c">more consistent, with fewer errors</a>.</p> <p>Finally, I drew back on an even older iMatix speciality, which was state machines. My first free software tool was <a href="http://legacy.imatix.com/html/libero/">Libero</a>, a great tool for designing code as state machines and producing lovely, solid engines in pretty much any language. Libero predates GSL, so isn't as flexible. However it uses a very elegant and simple state-event-action model.</p> <p>The Libero model is especially good at designing server-side logic, where you want to capture the exact state machine for a client connection, from start to end. This happens to be one of the more solid problems in ZeroMQ architecture: how to build capable protocol servers. We do a lot of this, it turns out. You can do only so much with low-level patterns like pub-sub and push-pull. Quite soon you need to implement stateful services.</p> <p>So this is what I made: a GSL code generator that takes a finite-state machine model inspired by Libero, and turns out a full working server. The current code generator produces C (that builds on CZMQ). In this article I'll explain briefly how this works, and how to use it.</p> <h2><span>The State Machine Model</span></h2> <p>State machines are a little unusual, conceptually. If you're not familiar with them it'll take a few days before they click. The Libero model is fairly simple and high level, meant to be designed and understood by humans:</p> <ul> <li>The machine exists in one of a number of named <em>states</em>. By convention the machine starts in the first state.</li> </ul> <ul> <li>In each state, the machine accepts one of a set of named <em>events</em>. Unhandled events are either ignored or cause the machine to die, depending on your taste.</li> </ul> <ul> <li>Given an event in a state, the machine executes a list of <em>actions</em>, which correspond to your code.</li> </ul> <ul> <li>After executing the actions the machine moves to the <em>next state</em>. An empty next state means &quot;stay in same state&quot;.</li> </ul> <ul> <li>In the next state, the machine either continues with an <em>internal event</em> produced by the previous actions, or waits for an <em>external event</em> coming as a protocol command.</li> </ul> <ul> <li>Any action can raise an <em>exception event</em> that interrupts the flow through the action list and to the next state.</li> </ul> <ul> <li>A <em>defaults state</em> collects events that may occur in any state, together with their actions.</li> </ul> <h2><span>The zproto Server Model</span></h2> <p>The zproto_server_c.gsl code generator outputs a single .h file called an <em>engine</em> that does the hard work. If needed, it'll also generate you a skeleton .c file for your server, which you edit and build. It doesn't re-create that file again, though it will append new action stubs.</p> <p>The server is a class that exposes an API like this (taken from the <a href="https://github.com/zeromq/zbroker/tree/master/src">zeromq/zbroker</a> zpipes_server, a good example):</p> <div class="code"> <pre><code>// Create a new zpipes_server zpipes_server_t * zpipes_server_new (void); // Destroy the zpipes_server void zpipes_server_destroy (zpipes_server_t **self_p); // Load server configuration data void zpipes_server_configure (zpipes_server_t *self, const char *config_file); // Set one configuration path value void zpipes_server_setoption (zpipes_server_t *self, const char *path, const char *value); // Binds the server to an endpoint, formatted as printf string long zpipes_server_bind (zpipes_server_t *self, const char *format, ...); // Self test of this class void zpipes_server_test (bool verbose);</code></pre></div> <p>Rather than run the server as a main program, you write a main program that creates and works with server objects. These run as background services, accepting clients on a ZMQ ROUTER port. The bind method exposes that port to the outside world.</p> <p>Here's the state machine for the ZPIPES server:</p> <div class="code"> <pre><code>&lt;class name = &quot;zpipes_server&quot; title = &quot;ZPIPES server&quot; proto = &quot;zpipes_msg&quot; script = &quot;zproto_server_c&quot; &gt; This is a server implementation for the ZPIPES protocol &lt;include filename = &quot;license.xml&quot; /&gt; &lt;!-- State machine for a client connection --&gt; &lt;state name = &quot;start&quot;&gt; &lt;event name = &quot;INPUT&quot; next = &quot;reading&quot;&gt; &lt;action name = &quot;open pipe for input&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;INPUT OK&quot; /&gt; &lt;/event&gt; &lt;event name = &quot;OUTPUT&quot; next = &quot;writing&quot;&gt; &lt;action name = &quot;open pipe for output&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;OUTPUT OK&quot; /&gt; &lt;/event&gt; &lt;/state&gt; This state allows two protocol commands, READ and CLOSE. Names of states, events, and actions are case insensitive. By convention we use uppercase for protocol events: &lt;state name = &quot;reading&quot;&gt; &lt;event name = &quot;READ&quot; next = &quot;expecting chunk&quot;&gt; &lt;action name = &quot;expect chunk on pipe&quot; /&gt; &lt;/event&gt; &lt;event name = &quot;CLOSE&quot;&gt; &lt;action name = &quot;close pipe&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;CLOSE OK&quot; /&gt; &lt;action name = &quot;terminate&quot; /&gt; &lt;/event&gt; &lt;/state&gt; This internal state shows how we make a decision in the state machine. These are three internal events; they can happen come immediately from 'expect chunk on pipe', or come later from various places. The server can ask for a wakeup event (timeout expired). We can also get events from other clients' machines. &lt;state name = &quot;expecting chunk&quot;&gt; &lt;event name = &quot;have chunk&quot; next = &quot;reading&quot;&gt; &lt;action name = &quot;clear pending reads&quot; /&gt; &lt;action name = &quot;fetch chunk from pipe&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;READ OK&quot; /&gt; &lt;/event&gt; &lt;event name = &quot;pipe terminated&quot; next = &quot;reading&quot;&gt; &lt;action name = &quot;clear pending reads&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;END OF PIPE&quot; /&gt; &lt;/event&gt; &lt;event name = &quot;timeout expired&quot; next = &quot;reading&quot;&gt; &lt;action name = &quot;clear pending reads&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;TIMEOUT&quot; /&gt; &lt;/event&gt; &lt;/state&gt; &lt;state name = &quot;writing&quot;&gt; &lt;event name = &quot;WRITE&quot; next = &quot;writing&quot;&gt; &lt;action name = &quot;store chunk to pipe&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;WRITE OK&quot; /&gt; &lt;/event&gt; &lt;event name = &quot;CLOSE&quot;&gt; &lt;action name = &quot;close pipe&quot; /&gt; &lt;action name = &quot;send&quot; message = &quot;CLOSE OK&quot; /&gt; &lt;action name = &quot;terminate&quot; /&gt; &lt;/event&gt; &lt;/state&gt; The defaults state handles an 'exception_event' (sends FAILED back to the client). It also specifies that any unrecognized protocol command (an '$other' event) will also cause the engine to send FAILED back to the client. &lt;state name = &quot;defaults&quot;&gt; &lt;event name = &quot;exception&quot;&gt; &lt;action name = &quot;send&quot; message = &quot;FAILED&quot; /&gt; &lt;action name = &quot;terminate&quot; /&gt; &lt;/event&gt; &lt;event name = &quot;$other&quot;&gt; &lt;action name = &quot;send&quot; message = &quot;FAILED&quot; /&gt; &lt;/event&gt; &lt;/state&gt; We can define API methods to pass commands back from the application through to the engine. &lt;!-- API methods &lt;method name = &quot;somename&quot; return = &quot;number&quot;&gt; One-line description of method here &lt;argument name = &quot;some value&quot; type = &quot;string&quot;&gt;What is this argument?&lt;/argument&gt; &lt;argument name = &quot;some value&quot; type = &quot;number&quot;&gt;What is this argument?&lt;/argument&gt; &lt;/method&gt; --&gt; &lt;/class&gt;</code></pre></div> <p>The generated server manages clients automatically. There's various options to expire dead clients, and so on — read the zproto_server_c.gsl code to understand more. The state machine applies to *single client connection* from start to finish.</p> <p>There are two predefined actions: &quot;send&quot; and &quot;terminate&quot;. Other actions map to functions in your own code. The engine calls these functions as needed, passing the client context:</p> <div class="code"> <pre><code>static void store_chunk_to_pipe (client_t *self) { // State machine guarantees we're in a valid state for writing assert (self-&gt;pipe); assert (self-&gt;writing); // Always store chunk on list, even to pass to pending reader zlist_append (self-&gt;pipe-&gt;queue, zpipes_msg_get_chunk (self-&gt;request)); if (self-&gt;pipe-&gt;reader) { send_event (self-&gt;pipe-&gt;reader, have_chunk_event); assert (zlist_size (self-&gt;pipe-&gt;queue) == 0); } }</code></pre></div> <p>There are a set of methods your actions can call:</p> <div class="code"> <pre><code>// Set the next event, needed in at least one action in an internal // state; otherwise the state machine will wait for a message on the // router socket and treat that as the event. static void set_next_event (client_t *self, event_t event); // Raise an exception with 'event', halting any actions in progress. // Continues execution of actions defined for the exception event. static void raise_exception (client_t *self, event_t event); // Set wakeup alarm after 'delay' msecs. The next state should // handle the wakeup event. The alarm is cancelled on any other // event. static void set_wakeup_event (client_t *self, size_t delay, event_t event); // Execute 'event' on specified client. Use this to send events to // other clients. Cancels any wakeup alarm on that client. static void send_event (client_t *self, event_t event);</code></pre></div> <h2><span>For More Information</span></h2> <p>Though <a href="http://legacy.imatix.com/html/libero/">the Libero documentation</a> is quite old now, it's useful as a guide to what's possible with state machines. The Libero model added superstates, substates, and other useful ways to manage larger state machines.</p> <p>The current working example of the zproto server generator is the <a href="https://github.com/zeromq/zbroker">zeromq/zbroker</a> project, and specifically the zpipes_server class.</p> <p>You can find <a href="https://github.com/imatix/gsl">GSL on Github</a> and there's a <a href="http://download.imatix.com/mop/">old backgrounder</a> for the so-called &quot;model oriented programming&quot; we used at iMatix.</p> <p>If you have something to say, comment below or come discuss on zeromq-dev.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:71</guid>
				<title>Cluster load-balancing using ZeroMQ over TIPC</title>
				<link>http://hintjens.wikidot.com/blog:71</link>
				<description>

&lt;p&gt;Erik Hugne writes, &amp;quot;I&#039;ve cooked up another example with real code illustrating load-balancing using the new TIPC transport for ZeroMQ. This demo uses overlapping port names.&amp;quot; The code &lt;a href=&quot;https://gist.github.com/hintjens/7335589&quot;&gt;is available to download&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 06 Nov 2013 12:56:57 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Erik Hugne writes, &quot;I've cooked up another example with real code illustrating load-balancing using the new TIPC transport for ZeroMQ. This demo uses overlapping port names.&quot; The code <a href="https://gist.github.com/hintjens/7335589">is available to download</a>.</p> <p>The REQ/REP load balancing example is using a small cluster with 4 nodes. A dummy service with ID=1000 is spawned on three nodes (1,2,3). Requests to this service ID are sent from Node 4.</p> <p>The dummy service is just listening for a message and prints it out once it arrives. It also sends a response message back to the client, telling it which host instance the message was handled by.</p> <p>First, load TIPC, assign node addresses and enable eth0 as the bearer interface. This is part of system configuration and is normally done by initscripts, but I'm including the steps for completeness.</p> <div class="code"> <pre><code>Node1# modprobe tipc &amp;&amp; tipc-config -a=1.1.1 -be=eth:eth0</code></pre></div> <div class="code"> <pre><code>Node2# modprobe tipc &amp;&amp; tipc-config -a=1.1.2 -be=eth:eth0</code></pre></div> <div class="code"> <pre><code>Node3# modprobe tipc &amp;&amp; tipc-config -a=1.1.3 -be=eth:eth0</code></pre></div> <div class="code"> <pre><code>Node4# modprobe tipc &amp;&amp; tipc-config -a=1.1.4 -be=eth:eth0</code></pre></div> <p>In this example, the nodes are KVM instances with the eth0 devices connected to a network bridge on the host machine.</p> <p>Starting the 0MQ service on Node 1-3:</p> <div class="code"> <pre><code>Node1# ./srv -s tipc://{1000,0,10} server tipc://{1000,0,10} running</code></pre></div> <div class="code"> <pre><code>Node2# ./srv -s tipc://{1000,0,10} server tipc://{1000,0,10} running</code></pre></div> <div class="code"> <pre><code>Node3# ./srv -s tipc://{1000,0,10} server tipc://{1000,0,10} running</code></pre></div> <p>Before sending any traffic, let's check how it looks like on our client Node4. Using tipc-config -nt, we can dump<br /> the whole, or parts of the name table.</p> <div class="code"> <pre><code>Node4# tipc-config -nt=1000 Type Lower Upper Port Identity Publication Scope 1000 0 10 &lt;1.1.3:2118189060&gt; 2118189061 cluster &lt;1.1.2:3767599108&gt; 3767599109 cluster &lt;1.1.1:1451425794&gt; 1451425795 cluster</code></pre></div> <p>Looks like we're good to go, Node4 knows that service 1000 is hosted by three nodes. Start sending some requests from Node4 to service 1000. Any instance number in the published range (0-10) can be used.</p> <div class="code"> <pre><code>Node4# ./cli -c {1000,4} Node4 sending message to: tipc://{1000,4} client sent message 'hello world from Node4', rc=25 Your request have been served by Node3 Node4# ./cli -c tipc://{1000,4} Node4 sending message to: tipc://{1000,4} client sent message 'hello world from Node4', rc=25 Your request have been served by Node2 Node4# ./cli -c tipc://{1000,4} Node4 sending message to: tipc://{1000,4} client sent message 'hello world from Node4', rc=25 Your request have been served by Node1 Node4# ./cli -c {1000,4} Node4 sending message to: tipc://{1000,4} client sent message 'hello world from Node4', rc=25 Your request have been served by Node3</code></pre></div> <p>Here we can see that each subsequent request are directed in a round robin manner between the instances running on Node1-3.</p> <p>Client applications can define their own policies/algorithms how to spread the instance numbers of the connections. By increasing/reducing the width of the server publications (the lower/upper numbers) for some of the blades, we can increase/reduce the number of connections handled by these blades.</p> <p>There are some rules that limits the TIPC name overlapping, these can be found in the TIPC programmers guide.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:70</guid>
				<title>The New TIPC Transport in ZeroMQ</title>
				<link>http://hintjens.wikidot.com/blog:70</link>
				<description>

&lt;p&gt;ZeroMQ now supports TIPC, the cluster IPC protocol developed by Ericsson. This will be part of the next major 4.1 release. In this article I&#039;ll interview Ericsson&#039;s Erik Hugne, the engineer who added this transport to ZeroMQ.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 04 Nov 2013 15:08:22 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>ZeroMQ now supports TIPC, the cluster IPC protocol developed by Ericsson. This will be part of the next major 4.1 release. In this article I'll interview Ericsson's Erik Hugne, the engineer who added this transport to ZeroMQ.</p> <p>Though ZeroMQ is great in many ways, it isn't easy to plug in different transports. So when we see a new transport like this, it's a sign of world class software engineering. I asked Erik a few questions, to learn more about TIPC, and why Ericsson added this to ZeroMQ.</p> <p><em>Pieter: First off, what's TIPC?</em></p> <p>Erik: TIPC is a cluster IPC protocol developed by Ericsson, it was initially a proprietary closed source solution, but both the specification and source code was released on Sourceforge early 2000, and picked up by the Linux kernel from v2.6.16.</p> <p><em>How does TIPC compare, for example, to TCP?</em></p> <p>TIPC provides a socket based API, supporting SOCK_STREAM, SOCK_RDM and SOCK_SEQPACKET. The ZeroMQ TIPC transport currently supports connection-oriented stream transmission (SOCK_STREAM), so the behaviour and characteristics of this are similar to that of TCP.</p> <p>Each node in a cluster establish logical links to its peers. These links are supervised actively with seamless failover to redundant links.</p> <p>TIPC guarantees in-order, sequential delivery on the link-level, even for connectionless (SOCK_RDM) and multicast traffic, given that the serving application is capable of keeping up with the load (we have no flow control for connectionless traffic).</p> <p>It comes with a distributed topology service that keeps track of all published services (bound sockets) in the cluster.</p> <p>Finally, TIPC can run over Ethernet and/or Infiniband.</p> <p><em>This sounds&#8230; extremely powerful. This means we can create clusters in just a few lines of code, using all the ZeroMQ patterns. I see you made a whole set of test cases for TIPC. Request-reply, pub-sub, the whole lot. Can you explain briefly how to use TIPC then?</em></p> <p>Sure. To use the TIPC transport, the serving ZeroMQ application needs to bind to a TIPC name sequence, a 3-tuple {type, lower, upper}. The 'type' is an ID that uniquely identifies your service in the cluster. The 'lower' and 'upper' are a service partitioning range that can be used for basic load balancing purposes. For example:</p> <div class="code"> <pre><code>zmq_bind (sb, &quot;tipc://{5560,0,100}&quot;);</code></pre></div> <p>And then for the client application to be able to connect, it specifies an ID in the range we defined above, for example:</p> <div class="code"> <pre><code>zmq_connect (sc, &quot;tipc://{5560,30}&quot;);</code></pre></div> <p><em>This is a Linux-only transport, which is fine for most people. How do I install TIPC?</em></p> <p>If you want to try it out, a Linux machine with kernel &gt;= 3.8 with <tt>CONFIG_TIPC=m</tt> is required.</p> <p><em>I'm going to have to play with this at some time and see how it handles failures.</em></p> <p>I'd like to emphasize here that you won't see a performance boost by switching to TIPC. There is no support for GRO (Generic Receive offload) yet, and the kernel code is not as mature as that of TCP/IP. In my opinion this starts to get really useful in a cluster environment once we have the RDM/Multicast support in place.</p> <p><em>Right, so the TIPC transport in ZeroMQ is about reliability, not performance.</em></p> <p>Yes, failover and load-balancing. You can do these on top of ZeroMQ, but when we can delegate it to TIPC, the results are better and it's invisible to the programmer. I'll embed it in a simple example using two qemu nodes, and simulating a failure on the primary link. This have almost the same effect as if a switch/port/cable fails.</p> <p>First, I need to assign node addresses, worth noting is that TIPC does not use per-interface addresses, but rather a node-global one.</p> <div class="code"> <pre><code>Node1# tipc-config -a=1.1.1 [...] tipc: Started in network mode [...] tipc: Own node address &lt;1.1.1&gt;, network identity 4711</code></pre></div> <p>I do the same thing on the second node, with the address &quot;1.1.2&quot;. Then, I tell TIPC to use Ethernet interfaces 'vlan100' and 'vlan200' (same thing done on the second node):</p> <div class="code"> <pre><code>Node2# tipc-config -be=eth:vlan100 [...] tipc: Enabled bearer &lt;eth:vlan100&gt;, discovery domain &lt;1.1.0&gt;, priority 10 [...] tipc: Established link &lt;1.1.2:vlan100-1.1.1:vlan100&gt; on network plane A Node2# tipc-config -be=eth:vlan200 [...] tipc: Enabled bearer &lt;eth:vlan200&gt;, discovery domain &lt;1.1.0&gt;, priority 10 [...] tipc: Established link &lt;1.1.2:vlan200-1.1.1:vlan200&gt; on network plane B</code></pre></div> <p>Now we start a netperf session from Node1 to Node2:</p> <div class="code"> <pre><code>Node1# netperf -H Node2 -t TIPC_STREAM -l 100 # /opt/netperf/netperf -H 192.168.1.78 -t TIPC_STREAM -l 100 TIPC STREAM TEST to &lt;1.1.2:3310419987&gt; [test running]</code></pre></div> <p>Here is how we check the link statistics on Node2 to see which link is currently the primary one:</p> <div class="code"> <pre><code>Link &lt;1.1.2:vlan100-1.1.1:vlan100&gt; ACTIVE MTU:1500 Priority:10 Tolerance:1500 ms Window:50 packets RX packets:298078 fragments:0/0 bundles:0/0 [...] Link &lt;1.1.2:vlan200-1.1.1:vlan200&gt; ACTIVE MTU:1500 Priority:10 Tolerance:1500 ms Window:50 packets RX packets:0 fragments:0/0 bundles:0/0 [...]</code></pre></div> <p>Th top one is primary (see the RX packets), so let's bring that device down, simulating a crash:</p> <div class="code"> <pre><code>Node2# ip link set vlan100 down [...] tipc: Blocking bearer &lt;eth:vlan100&gt; [...] tipc: Lost link &lt;1.1.2:vlan100-1.1.1:vlan100&gt; on network plane A</code></pre></div> <p>Node1 reacts to this immediately and does a changeover to link 2:</p> <div class="code"> <pre><code>[...] tipc: Resetting link &lt;1.1.1:vlan100-1.1.2:vlan100&gt;, changeover initiated by peer [...] tipc: Lost link &lt;1.1.1:vlan100-1.1.2:vlan100&gt; on network plane A</code></pre></div> <p>Despite the failure and recovery, our transmission continues happily, unacked messages that were already sent out on the failed link will be retransmitted on the new primary one after the changeover:</p> <div class="code"> <pre><code>Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 34120200 212992 212992 100.00 648.45</code></pre></div> <p>Regarding load balancing, I'll write a demo application for that soon. In the meantime, here's an example in pseudocode that will help you to understand the concept.</p> <p>The same service is published on both node1 and node2, using partially overlapping names:</p> <div class="code"> <pre><code>Node1: [...] zmq_bind (sd, &quot;tipc://{1000,0,1} [...] Node2: [...] zmq_bind (sd &quot;tipc://{1000,1,2} [...] [[/node]] Now, a client on Node3 wanting to use this service can do so by connecting to either: [[code]] A = zmq_connect (sc, &quot;tipc://{1000,0}&quot;) B = zmq_connect (sc, &quot;tipc://{1000,1}&quot;) C = zmq_connect (sc, &quot;tipc://{1000,2}&quot;)</code></pre></div> <p>Load balancing works this way:</p> <ul> <li>A only matches the service published by Node1.</li> <li>C only matches the service published by Node2.</li> <li>B matches both Node1 and Node2. TIPC will do round-robin selection between these two, spreading out the connections evenly.</li> </ul> <p>There's still a missing feature in the code that's on libzmq master right now. By default, TIPC sets the &quot;lookup domain&quot; to closest first. This means that if there is a published service on the local machine that matches your request, that will be used for <em>all</em> requests, even when you spread your service over multiple nodes.</p> <p>So, either I will add a way for the application to specify the lookup domain in the connect string, or I'll set the default lookup domain to always do round-robin over the entire cluster.</p> <p>The <a href="http://tipc.sourceforge.net/doc/tipc_2.0_prog_guide.html#using_port_names">TIPC 2.0 Programmer's Guide</a> explains a little about how name sequences work.</p> <p><em>Thank you so much, Erik, for this excellent addition to ZeroMQ, and your explanations. What are your plans for TIPC support in future versions of ZeroMQ?</em></p> <p>Looking forward, we'd like to extend this with a RDM multicast transport module as well, which will make it very fast. This would add the ability to reliably send a series of messages to 0..n recipients. We are also investigating how to expose the topology service to ZeroMQ applications in a portable way.</p> <p><em>I'm looking forward to this. Incidentally, the TIPC transport will appear in ZeroMQ v4.1</em></p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:62</guid>
				<title>ZeroMQ Certificates, Design Iteration 1</title>
				<link>http://hintjens.wikidot.com/blog:62</link>
				<description>

&lt;p&gt;In the ongoing search for a new certificate format for ZeroMQ, I kicked off a &lt;a href=&quot;http://thread.gmane.org/gmane.network.zeromq.devel/20532&quot;&gt;nice lively thread on zeromq-dev&lt;/a&gt; with some to and for, little agreement, and lots of ideas. In this article I&#039;ll present Design Iteration 1, a strawman that people can beat up. The format is inspired by the &lt;a href=&quot;http://www.ietf.org/rfc/rfc4716.txt&quot;&gt;SSH2 public key format&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 14 Oct 2013 12:20:49 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>In the ongoing search for a new certificate format for ZeroMQ, I kicked off a <a href="http://thread.gmane.org/gmane.network.zeromq.devel/20532">nice lively thread on zeromq-dev</a> with some to and for, little agreement, and lots of ideas. In this article I'll present Design Iteration 1, a strawman that people can beat up. The format is inspired by the <a href="http://www.ietf.org/rfc/rfc4716.txt">SSH2 public key format</a>.</p> <h2><span>Goals and Requirements</span></h2> <p>These are the requirements I wrote down when designing this certificate format:</p> <ul> <li>The core goal is to give people a format they can reuse, rather than ask every project that uses ZeroMQ security to invent their own format. A single format lets different applications <em>interoperate</em>, and lets us make a few 10-day projects that work together instead of 100&#160;2-day projects that cannot.</li> </ul> <ul> <li>The format we use has to be <em>simple</em> and <em>human readable</em>. It has to be <em>portable</em> to any system and <em>obvious</em> to implement, and <em>language-neutral</em>.</li> </ul> <ul> <li>A certificate must be capable of carrying at least the CURVE security keys, but should be <em>extensible</em> to any security mechanism, given that ZeroMQ is itself extensible to new security mechanisms.</li> </ul> <ul> <li>A certificate may be <em>symmetrically encrypted with a passphrase</em>, if it holds secret information. We should use a standard encryption algorithm to ensure interoperability.</li> </ul> <ul> <li>A certificate may be <em>asymmetrically encrypted to a recipient</em>, when it will be sent across an untrusted channel. We should use a standard authentication and encryption mechanism to ensure interoperability.</li> </ul> <ul> <li>The certificate must be <em>safe to copy/paste into email</em>, and it must be possible to <em>automatically extract one or more certificates</em> from an email message.</li> </ul> <ul> <li>The certificate should be <em>easy to verify</em> by hand (e.g. over a voice call), using a text fingerprint.</li> </ul> <h2><span>Use Cases</span></h2> <p>These are the use cases I know about for the CURVE security mechanism:</p> <ul> <li>A server generates a public + secret keypair, stores the secret key securely, using a passphrase, and stores the public key in clear text. This creates two certificate files, one meant to be kept locally, and one meant to be published.</li> </ul> <ul> <li>A client receives a public certificate from a server. It stores this in a location where it can access it at run time, when it needs that server's public key.</li> </ul> <ul> <li>A client generates a public + secret keypair, stores the secret key securely, using a passphrase, and encrypts and signs the public key from its own secret key to the server's public key.</li> </ul> <ul> <li>A server receives a signed and encrypted public certificate from a client. It stores this in a location where it can access it at run time, when the client makes a new connection.</li> </ul> <h2><span>Argumentation</span></h2> <h3><span>One Envelope, many Contents</span></h3> <p>To support arbitrary security mechanisms, it seems useful to split the envelope (how the certificate is represented) from the content (the security keys and metadata). Specifically:</p> <ul> <li>The envelope will always be in clear text, while the content may be encrypted.</li> <li>The envelope will have a small set of standard properties, while the content should be fully extensible.</li> <li>The envelope will rarely change, while the content will change frequently over time as we refine our security mechanisms.</li> <li>We would create and process the envelope, and contents, at two different layers, a generic certificate codec, and a specific layer for each different mechanism.</li> </ul> <p><strong>Figure 1 - Two-layer Certificate</strong></p> <div class="image-container aligncenter"><img src="http://hintjens.wdfiles.com/local--files/blog:62/fig1.png" alt="fig1.png" class="image" /></div> <p>So, in this article I'll aim towards (a) a certificate envelope format and (b) a certificate content format for CURVE.</p> <h3><span>Email Armoring</span></h3> <p>This is a common problem with a well-known solution. To let us copy/paste a certificate into an email, and extract certificates from emails, we put a special marker before and after the certificate. Let's use this style:</p> <div class="code"> <pre><code>-----BEGIN ZEROMQ CERTIFICATE----- ... -----END ZEROMQ CERTIFICATE-----</code></pre></div> <p>Further, lines must be at most 72 characters long, and we should use only 7-bit ASCII.</p> <h3><span>Envelope Format</span></h3> <p>In the envelope we will want to note:</p> <ul> <li>The version number for the envelope, so we can assure forward compatibility.</li> <li>The mechanism name, so that the codec can pass decrypted content to the correct mechanism.</li> <li>Whether the content is encrypted, and if so, using what algorithm.</li> <li>Whether the content is signed, and if so, using what algorithm and public key.</li> </ul> <p>A simple and well-understood format for the envelope is HTTP-style headers, e.g.:</p> <div class="code"> <pre><code>Version: 0.1 Mechanism: CURVE Comment: The certificate content is signed by the sender using their s\ ecret key and encrypted to the recipient's public key. We put both pub\ lic keys into the envelope so the reader can decrypt using the right s\ ecret key. Here, the &quot;Content-security&quot; header is actually redundant. Content-security: signed Content-signed-by: Yne@$w-vo&lt;fVvi]a&lt;NY6T1ed:M$fCG*[IaLV{hID Content-signed-to: rq:rM&gt;}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7</code></pre></div> <p>Note that we're splitting long lines at column 72 and using a backwards slash to indicate that the line continues. This makes the text safe to send in emails.</p> <h3><span>Content Format</span></h3> <p>ZeroMQ is notable for transporting opaque frames without trying to define their internal structure. We can do the same here and reuse the successful pattern where the content consists of zero or more opaque frames. Having said that, we should also standardize the content for at least the CURVE mechanism we want to support today. Presumably in two separate RFCs.</p> <p>We will want a consistent syntax for content framing so the codec can do its work. Since we're building a text format, we can define a frame as a single line of text. We can use the same continuation line style as we did with headers.</p> <p>In ZeroMQ's security model, all mechanisms have metadata, which consists of zero or more name=value pairs. We can specify that the metadata sits in the first frame, and that other mechanism-specific properties follow in further frames. To indicate an empty frame, let's use a single hyphen, &quot;-&quot;.</p> <p>Here is the sketch of a PLAIN certificate with metadata, name, and password as three frames:</p> <div class="code"> <pre><code>-----BEGIN ZEROMQ CERTIFICATE----- Version: 0.1 Mechanism: PLAIN Uuid=b19e19a0-34aa-11e3-aa6e-0800200c9a66;Date-created=14 October, 2013\ ;Created-by=Pieter Hintjens;Email=ph@imatix.com admin topsecret -----END ZEROMQ CERTIFICATE-----</code></pre></div> <p>Note that the metadata is using a <em>name=value</em> format, with semicolons to separate pairs. In ZMQ RFC 23, metadata names are case-insensitive, so we'll use that convention here too.</p> <p>Overall this looks somewhat like the SSH 2 public key format (<a href="http://www.ietf.org/rfc/rfc4716.txt">IETF RFC 4716</a>), but is adapted to the ZeroMQ extensible security model. As in IETF RFC 4716 we do not use a blank line between headers and content since it serves no purpose. The headers continue as long as there is a line containing &quot;: &quot;.</p> <h3><span>Binary Content Encoding</span></h3> <p>When we encrypt the content, all frames have to be encrypted the same way. We could encrypt each frame individually but this exposes the frame structure to anyone who reads the certificate. Instead, we'll write the whole content (all frames) into a buffer, including line endings, and then encrypt that whole buffer. We will then use the ZMQ RFC 32 (Z85) encoding to represent the binary data safely as text. Z85 is more compact than Base16 or Base64, and the ZeroMQ core API provides encoding and decoding methods. Like all ASCII armoring, Z85 requires padding. To allow safe decoding of Z85 data we need to know the size of the data, excluding any padding. For double-checking we also need the padded length, i.e. the actual number of characters in the encoded content.</p> <p>To authenticate a certificate, we need to verify the encrypted content, e.g. over the phone. This is not practical for typically long encrypted content. We thus use the SSH standard for generating an MD5 digest of the content. MD5 has known security weaknesses: you can modify a content and generate the same hash, if you can insert 128 bytes of data at some point. Since our encrypted content has a structure that is unknowable without decryption, it cannot be successfully modified. Thus, MD5 provides an acceptable signature. We will use the SSH-style signature consisting of a sequence of 16 octets printed as lower-case hexadecimal and separated by colons.</p> <p>We can place the content sizes and signature in a first frame, and the armored text into a second frame. As before, we can continue long frames over multiple lines. So this gives us, for example:</p> <div class="code"> <pre><code>381,384,c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87 nP2U)xK@r8zF9)4zF78kwNPQ?xDQ]9AV!^kzE[2mv}xX5x&gt;z6?vru66w]zZbvrrS7z/M$7w\ PzY-q7J?YazUX3yH}30z!pb2ax@J3Bz%n]fly(FwNPa4xkI6{wId[wxd)[mvqYTezE){lz/\ PRCDs.bnze?gswP?T3fetjsgCQ7&lt;x&gt;7Y%y?X67y&lt;vdBxMvV)wft/daBmQtz/6FCwmY{&amp;aA}\ KwxDRwmzdK&amp;izY&amp;FawftG5AX5tHx([DkwGUz]A+e*0wO#PvayPd#az+$rB0bykazCv$vrj4\ znP2U)xLzJgvrcE7v@bZ0nHFs&lt;aAhvjB7GlhayMylBAg/laz&gt;L8aARp9BrCKlz/xJ7ay!?$\ ayX[&lt;Bs[WUra]?=w]zZbvrrSaB0a}2B7F(8z/cXtxK@q&lt;xMOuniXJdgCxUVNwPRJpz/PFzA\ +n/mA+n/rh.^iyBA?)Iq=ujxaAhEjy?Wx4yH}=lw]zZbvrt^c3ig5a</code></pre></div> <p>To ensure that the same content survives decoding and re-encoding across multiple platforms, we will specify that the buffered content may only contain LF as its end of line marker. Carriage return characters in the decoded content should be treated as a fatal error, and the certificate rejected.</p> <h2><span>Technical Proposal - Certificate Envelope Format</span></h2> <h3><span>Syntax and Grammar</span></h3> <p>Here's a <a href="http://en.wikipedia.org/wiki/Augmented_Backus%E2%80%93Naur_Form">ABNF grammar</a> for the certificate envelope format:</p> <div class="code"> <pre><code>certificate = begin *header content end begin = &quot;-----BEGIN ZEROMQ CERTIFICATE-----&quot; eoln eoln = CR | LF | CRLF header = header-name &quot;: &quot; header-value eoln header-name = defined-header / extension-header defined-header = &quot;Version&quot; / &quot;Mechanism&quot; / &quot;Content-security&quot; / &quot;Content-signed-by&quot; / &quot;Content-signed-to&quot; / &quot;Comment&quot; extension-header = &quot;X-&quot; 1*62(LETTER / DIGIT / &quot;-&quot;) header-value = *header-cont header-last header-cont = 1*CHAR &quot;\&quot; eoln header-last = 1*CHAR eoln content = *clear-frame / content-crypt clear-frame = &quot;-&quot; / (*clear-cont clear-last) clear-cont = 1*71CHAR &quot;\&quot; eoln clear-last = 1*72CHAR eoln content-crypt = length-frame armored-frame length-frame = 1*DIGIT &quot;,&quot; 1*DIGIT &quot;,&quot; signature signature = 15(signature-octet &quot;:&quot;) signature-octet signature-octet = 2(DIGIT / &quot;a&quot; / &quot;b&quot; / &quot;c&quot; / &quot;d&quot; / &quot;e&quot; / &quot;f&quot; ) armored-frame = *armored-cont armored-last armored-cont = 1*71armored-char &quot;\&quot; eoln armored-last = 1*72armored-char eoln armored-char = DIGIT / LETTER / &quot;.&quot; / &quot;-&quot; / &quot;:&quot; / &quot;+&quot; / &quot;=&quot; / &quot;^&quot; / &quot;!&quot; / &quot;/&quot; / &quot;*&quot; / &quot;?&quot; / &quot;&amp;&quot; / &quot;&lt;&quot; / &quot;&gt;&quot; / &quot;(&quot; / &quot;)&quot; / &quot;[&quot; / &quot;]&quot; / &quot;{&quot; / &quot;}&quot; / &quot;@&quot; / &quot;%&quot; / &quot;$&quot; / &quot;#&quot; end = &quot;-----END ZEROMQ CERTIFICATE-----&quot; eoln</code></pre></div> <p>Notes on this syntax:</p> <ul> <li>Header names are case-insensitive, while header values are case-sensitive.</li> <li>The order of headers is not relevant except that a second header with the same name as the first will override the first header.</li> <li>Header values are limited to 1,024 characters. RFC 4716 allows quoted values but this adds nothing so I've not allowed that.</li> <li>The content starts on the first line not containing &quot;: &quot;.</li> </ul> <h3><span>The Version Header</span></h3> <p>Specifies the version of the certificate format used. This header is mandatory. It may have these values:</p> <ul> <li>0.1 - specifies draft version 1. Draft versions do not provide any guarantee of backwards compatibility.</li> </ul> <h3><span>The Mechanism Header</span></h3> <p>Specifies the security mechanism that the certificate implements. This header is mandatory. It may have these values:</p> <ul> <li>PLAIN - implements the ZeroMQ PLAIN mechanism, as defined by ZMQ RFCs 24.</li> <li>CURVE - implements the ZeroMQ CURVE mechanism, as defined by ZMQ RFCs 25 and 26.</li> </ul> <p>The content depends on the mechanism and will be defined separately for each standardized mechanism.</p> <h3><span>The Content-security Header</span></h3> <p>Specifies whether the content is encrypted and how. This header is optional. It may have these values:</p> <ul> <li>clear - the content is carried as clear text.</li> <li>password - the content is encrypted using a symmetric key derived from a user-supplied password, using the scrypt algorithm. <em>Note: this needs more study and explanation.</em></li> <li>signed - the content is authenticated and encrypted using the <tt>crypto_box</tt> function of NaCl or libsodium.</li> </ul> <p>If the Content-signed-by and Content-signed-to headers are present, Content-security defaults to &quot;signed&quot;, else to &quot;plain&quot;.</p> <h3><span>The Content-signed-by Header</span></h3> <p>When Content-security is &quot;signed&quot;, specifies the sender's public key used to authenticate the content. The key is provided in Z85 format and must be 40 characters long. The recipient uses this to authenticate the certificate content (not the certificate itself, which must be authenticated by some other channel).</p> <h3><span>The Content-signed-to Header</span></h3> <p>When Content-security is &quot;signed&quot;, specifies the recipient's public key used to encrypt the content. The key is provided in Z85 format and must be 40 characters long. The recipient uses this to find the correct secret key to decrypt the content.</p> <h3><span>The Comment Header</span></h3> <p>Contains a user-specified comment. The comment MAY be displayed when using the key. The comment MUST be stored with the certificate and copied if the certificate is recreated on disk.</p> <h3><span>Validating a Certificate</span></h3> <p>When reading a certificate, these are the minimum set of validations the code should do. A certificate that fails any of these checks can be considered invalid:</p> <ul> <li>The certificate has valid begin and end lines.</li> <li>The version and mechanism headers are present, and have valid values.</li> <li>The content, if encrypted, has a valid size and fingerprint.</li> </ul> <h2><span>Technical Proposal - PLAIN Certificate Content Format</span></h2> <p>The PLAIN mechanism uses these frames:</p> <ul> <li>Frame 1 is metadata, as with all mechanisms.</li> <li>Frame 2 is the username.</li> <li>Frame 3 is the password.</li> </ul> <p>A PLAIN certificate:</p> <ul> <li>MAY use signed content security when it is sent across insecure channels.</li> </ul> <h2><span>Technical Proposal - CURVE Certificate Content Format</span></h2> <p>The CURVE mechanism uses these frames:</p> <ul> <li>Frame 1 is metadata, as with all mechanisms.</li> <li>Frame 2 is the public key, and is always present.</li> <li>Frame 3 is the matching secret key, and is optional.</li> </ul> <p>A CURVE certificate:</p> <ul> <li>MUST use signed content security, and MUST not contain a secret key, when it is sent across insecure channels.</li> <li>MAY use password security, when it is held for a peer's own use.</li> <li>MUST use clear security when it is meant to be published openly to all recipients.</li> </ul> <h2><span>Conclusions</span></h2> <p>I've presented a hopefully simple certificate format that can store anything we need to implement ZeroMQ mechanisms at server or client, and which can be extended to new mechanisms. What's missing here is some proposal for standard filenames and certificate locations on disk. This should be part of a standard specification, I think.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:53</guid>
				<title>Securing ZeroMQ: Soul of a New Certificate</title>
				<link>http://hintjens.wikidot.com/blog:53</link>
				<description>

&lt;p&gt;While wrapping ZeroMQ&#039;s new security API up in the &lt;a href=&quot;http://czmq.zeromq.org&quot;&gt;high-level C binding&lt;/a&gt;, I accidentally a certificate format. With all respect to X.509 and existing PKI standards, the reason I built CURVE for ZeroMQ was to get simple and foolproof security. Using a complex legacy certificate format would spoil the soup. I&#039;ve no idea what the right format is, but to start, I&#039;m going to try to collect requirements.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 01 Oct 2013 07:54:05 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>While wrapping ZeroMQ's new security API up in the <a href="http://czmq.zeromq.org">high-level C binding</a>, I accidentally a certificate format. With all respect to X.509 and existing PKI standards, the reason I built CURVE for ZeroMQ was to get simple and foolproof security. Using a complex legacy certificate format would spoil the soup. I've no idea what the right format is, but to start, I'm going to try to collect requirements.</p> <p>The following list is meant for discussion. Based on that, I'll edit this post into shape and come up with some proposals that we can beat into shape.</p> <h2><span>Syntax vs. Semantics</span></h2> <p>To start with, do we need a single standard file format? I think no, it doesn't matter what format a certificate is stored in, as long as it's convertible. That means consistent semantics. One name for a thing, where the name is formally defined. But whether we use JSON, XML, YAML, or hand-crafted 13-bit binary formats, does not really matter.</p> <h2><span>Extensibility</span></h2> <p>My pet mechanism for ZeroMQ is CURVE, which implements the CurveZMQ handshake. However people are already starting to design other mechanisms for ZeroMQ, which has an extensible security model. Do we want to have a new certificate discussion for every mechanism? I think it would be better to have one format that different mechanisms can reuse (if they want to, since some mechanisms will already have their own certificate formats). Since each mechanism will have its own requirements, how about an extensible certificate format?</p> <h2><span>Metadata Headers</span></h2> <p>Certificates probably need some place to store metadata, such as the name of the person who this certificate identifies, partly to make management easier, perhaps also for authentication and access control. Let's say metadata consists of a set of named properties, without hierarchy. Let's make the names case-insensitive to avoid mistakes when people type them by hand.</p> <h2><span>Multilevel Certificates</span></h2> <p>At least for CURVE, we need two certificates; a public one (metadata + public key), and a secret one (metadata + public key + secret key). For the application, this could maybe be transparent, or abstracted in some way.</p> <h2><span>A Standard API</span></h2> <p>Speaking of applications, if we have a standard certificate format for ZeroMQ applications, shouldn't we also have a standard API to work with them? That could even be embedded into the core libzmq API so that it's available to all language bindings. By &quot;work with&quot;, I mean at least creating but also possibly parsing certificates.</p> <h2><span>Encryption of Secret Keys</span></h2> <p>Having a secret key in plain view is troublesome since it's too easy to leave a directory readable to other processes. Even if applications check that secret certificates have the right permissions, that doesn't guard against any exploit that gets root access. So perhaps we need passphrase encryption of the certificate, where the client application can prompt the user for the passphrase when starting up.</p> <h2><span>Certificate Signing</span></h2> <p>I don't see a way to safely share a certificate without some shared secret, or resorting to a third party, CA-style. Even if I encrypt the certificate with the recipient's public key, they can't authenticate that without knowing my public key in advance. Is there a simple answer to this?</p> <h2><span>Public Infrastructure</span></h2> <p>Some people will certainly build certificate servers, but do we want this to be part of the certificate design? I think that's a strong &quot;no&quot; since it raises the barrier for even simple cases. A certificate format should be simple for simple case.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:49</guid>
				<title>Using ZeroMQ Security (part 2)</title>
				<link>http://hintjens.wikidot.com/blog:49</link>
				<description>

&lt;p&gt;In the &lt;a href=&quot;http://hintjens.com/blog:48&quot;&gt;previous article&lt;/a&gt; I gave an overview of how and why ZeroMQ&#039;s security layers work. In this article I&#039;ll develop a simple secure application, step by step. We&#039;ll use a simple example of a server PUSH socket sending &amp;quot;Hello&amp;quot; to a client PULL socket. We&#039;ll work through the ZeroMQ NULL, PLAIN, and CURVE security mechanisms, up to full authentication. The examples are in C but the principles apply to all languages.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 19 Sep 2013 21:07:55 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>In the <a href="http://hintjens.com/blog:48">previous article</a> I gave an overview of how and why ZeroMQ's security layers work. In this article I'll develop a simple secure application, step by step. We'll use a simple example of a server PUSH socket sending &quot;Hello&quot; to a client PULL socket. We'll work through the ZeroMQ NULL, PLAIN, and CURVE security mechanisms, up to full authentication. The examples are in C but the principles apply to all languages.</p> <table style="margin:0; padding:0"> <tr> <td style="margin:0; padding:0"> <div id="toc"> <div id="toc-action-bar"><a href="javascript:;" >Fold</a><a style="display: none" href="javascript:;" >Unfold</a></div> <div class="title">Table of Contents</div> <div id="toc-list"> <div style="margin-left: 2em;"><a href="#toc0">Requirements &amp; Kicking Off</a></div> <div style="margin-left: 2em;"><a href="#toc1">What We'll Make</a></div> <div style="margin-left: 2em;"><a href="#toc2">The Grasslands Pattern</a></div> <div style="margin-left: 2em;"><a href="#toc3">The Strawhouse Pattern</a></div> <div style="margin-left: 2em;"><a href="#toc4">The Woodhouse Pattern</a></div> <div style="margin-left: 2em;"><a href="#toc5">The Stonehouse Pattern</a></div> <div style="margin-left: 2em;"><a href="#toc6">The Ironhouse Pattern</a></div> <div style="margin-left: 2em;"><a href="#toc7">The Ironhouse Pattern, Model 2</a></div> <div style="margin-left: 2em;"><a href="#toc8">Wrapping Up</a></div> </div> </div> </td> </tr> </table> <h2><span>Requirements &amp; Kicking Off</span></h2> <p>For this tutorial you will ZeroMQ v4.0, CZMQ v2.0, and Sodium (the crypto library). We will build from source, since we're going to be coding anyhow. You can grab these either as download packages (here's <a href="https://download.libsodium.org/libsodium/releases/">Sodium</a>, <a href="http://zeromq.org/intro:get-the-software">ZeroMQ</a>, and <a href="http://czmq.zeromq.org/page:get-the-software">CZMQ</a>), or from GitHub (here's <a href="https://github.com/jedisct1/libsodium">Sodium</a>, <a href="https://github.com/zeromq/libzmq">ZeroMQ</a>, and <a href="https://github.com/zeromq/czmq">CZMQ</a>).</p> <p>Sodium is a packaging of the <a href="http://nacl.cr.yp.to/">NaCl crypto library</a>, which implements the Curve25519 elliptic curve cryptography (ECC) algorithm. It doesn't matter for this tutorial, but when you use ECC in real work, people will ask you (a) isn't ECC backdoored by the NSA?, and (b) how secure is this, and (c) how fast is it, and (d) who else uses it?</p> <p>The answers are, at least today, (a) some ECC curves may be, and older crypto like RSA probably is, but Curve25519 is not, (b) it provides 256 bit ECC keys which is as strong as 3072 RSA keys, and (c) it's one of the fastest elliptic curves out there. Also, (d) it's not exactly mainstream, but is gaining popularity and Google is using it for their Quik protocol.</p> <p>I'll assume you're working on Linux or OS/X and have gcc or similar installed, and some idea of how to compile and link C programs. The API I'll use is that provided by CZMQ. If you are working in another language, it may or may not provide the same level of abstraction. I'll explain what CZMQ is doing, in any case.</p> <p>Here's how to build from GitHub (building from packages is very similar, you don't clone a repo but unpack a tarball):</p> <div class="code"> <pre><code>git clone git://github.com/jedisct1/libsodium.git cd libsodium ./autogen.sh ./configure &amp;&amp; make check sudo make install sudo ldconfig cd .. git clone git://github.com/zeromq/libzmq.git cd libzmq ./autogen.sh ./configure &amp;&amp; make check sudo make install sudo ldconfig cd .. git clone git://github.com/zeromq/czmq.git cd czmq ./autogen.sh ./configure &amp;&amp; make check sudo make install sudo ldconfig cd ..</code></pre></div> <p>Next, let's check that things are working, with a minimal example:</p> <div class="code"> <p><span style="color:#BC7A00">#include &lt;czmq.h&gt;</span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>publisher <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PUB);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_curve_server (publisher, <span style="color:#008000">true</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (<span style="color:#BA2121">&quot;Hello, Curve!&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>hello.c: Hello, Curve</em> <p>Here's how I build and run this:</p> <div class="code"> <pre><code>gcc -o hello hello.c -lczmq -lzmq -lsodium ./hello</code></pre></div> <p>If that prints &quot;Hello, Curve&quot;, then you're on the road to success. If not, check you have the necessary packages. On Debian/Ubuntu, you'll need <tt>build-essential</tt>, for instance.</p> <h2><span>What We'll Make</span></h2> <p>We'll make a minimal server-to-client PUSH-PULL flow with one server and one client. To make things really simple, the server will bind, the client will connect, and the server will send one message to the client:</p> <p><strong>Figure 1 - Minimal Server to Client</strong></p> <div class="image-container aligncenter"><img src="http://hintjens.wdfiles.com/local--files/blog:49/fig1.png" alt="fig1.png" class="image" /></div> <p>I'm going to make this in five steps, so you can see the different security patterns that are possible with today's ZeroMQ. To make it easy to remember these five patterns, I've given them mnemonic names:</p> <ul> <li><strong>Grasslands</strong>, which is plain text with no security at all. All connections are accepted, there is no authentication, and no privacy. This is how ZeroMQ always worked until we build security into the wire protocol in early 2013. Internally, it uses a security mechanism called &quot;NULL&quot;, but you don't even see that.</li> </ul> <ul> <li><strong>Strawhouse</strong>, which is plain text with filtering on IP addresses. We still use the NULL mechanism, but we install an authentication hook (I'll explain this in a second) that checks the IP address against a whitelist or blacklist and allows or denies it accordingly.</li> </ul> <ul> <li><strong>Woodhouse</strong>, which extends Strawhouse with a name and password check. For this, we use a mechanism called &quot;PLAIN&quot; (which does plain-text username and password authentication). It's still really not secure, and anyone sniffing the network (trivial with WiFi) can capture passwords and then login as if they were the real Joe.</li> </ul> <ul> <li><strong>Stonehouse</strong>, which switches to the &quot;CURVE&quot; security mechanism, giving us strong encryption on data, and (as far as we know) unbreakable authentication. Stonehouse is the minimum you would use over public networks, and assures clients that they are speaking to an authentic server, while allowing any client to connect.</li> </ul> <ul> <li><strong>Ironhouse</strong>, which extends Stonehouse with client public key authentication. This is the strongest security model we have today, protecting against every attack we know about, except end-point attacks (where an attacker plants spyware on a machine to capture data before it's encrypted, or after it's decrypted).</li> </ul> <p>As I said in my last article, privacy is about cost, and these patterns get increasingly expensive to use. Stonehouse and Ironhouse are not as easy to deploy as TLS, for instance. But they are also much more expensive to break, and for most ZeroMQ users that is a good tradeoff.</p> <h2><span>The Grasslands Pattern</span></h2> <p>We'll kick off with the simplest possible example, which looks just like classic ZeroMQ code, because it is:</p> <div class="code"> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Grasslands Pattern<br /> <span style="white-space: pre-wrap;">//</span><br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Classic ZeroMQ model, plain text with no protection at all.</span></span></p> <p><span style="color:#BC7A00">#include &lt;czmq.h&gt;</span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create context</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and bind server socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>server <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PUSH);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (server, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:9000&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and connect client socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>client <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PULL);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (client, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>127.0.0.1:9000&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send a single message from server to client</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (server, <span style="color:#BA2121">&quot;Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>message <span style="color:#666666">=</span> zstr_recv (client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (streq (message, <span style="color:#BA2121">&quot;Hello&quot;</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (message);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (<span style="color:#BA2121">&quot;Grasslands test OK&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>grasslands.c: Grasslands Pattern</em> <p>To keep the code short and focus on the API calls, I'm not handling errors here. This is fun, but dangerous, like driving a motorbike without a seatbelt. In practice, since your code <em>will</em> fail in lots of unexpected places, it's wise to catch at least the more basic problems early on.</p> <p>When you start to use the ZeroMQ and CZMQ security APIs, the main symptom of confusion will be &quot;nothing happens&quot;, in other words, there's no connection when you expect one. To make sure it's not a basic bind/connect error, at least check the return codes from those two calls. For example:</p> <div class="code"> <pre><code>int rc = zsocket_bind (server, &quot;tcp://*:9000&quot;); // If the bind fails, don't even attempt to recover assert (rc != -1);</code></pre></div> <p>There are people who hate asserts, but they're an extremely useful and brutal tool for forcing your code through a single sane path, and giving you accurate and early proof of errors.</p> <h2><span>The Strawhouse Pattern</span></h2> <p>Our next model takes the same code and adds address checking. I'll explain what we're doing and how it works in detail, first here is the application code:</p> <div class="code"> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Strawhouse Pattern<br /> <span style="white-space: pre-wrap;">//</span><br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We allow or deny clients according to their IP address. It may keep<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>spammers and idiots away, but won't stop a real attacker for more<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>than a heartbeat.</span></span></p> <p><span style="color:#BC7A00">#include &lt;czmq.h&gt;</span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create context</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start an authentication engine for this context. This engine</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>allows or denies incoming connections (talking to the libzmq</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>core over a protocol called ZAP).</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zauth_t</span> <span style="color:#666666">*</span>auth <span style="color:#666666">=</span> zauth_new (ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Get some indication of what the authenticator is deciding</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_set_verbose (auth, <span style="color:#008000">true</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Whitelist our address; any other address will be rejected</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_allow (auth, <span style="color:#BA2121">&quot;127.0.0.1&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and bind server socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>server <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PUSH);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_zap_domain (server, <span style="color:#BA2121">&quot;global&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (server, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:9000&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and connect client socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>client <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PULL);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (client, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>127.0.0.1:9000&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send a single message from server to client</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (server, <span style="color:#BA2121">&quot;Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>message <span style="color:#666666">=</span> zstr_recv (client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (streq (message, <span style="color:#BA2121">&quot;Hello&quot;</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (message);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (<span style="color:#BA2121">&quot;Strawhouse test OK&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_destroy (<span style="color:#666666">&amp;</span>auth);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>strawhouse.c: Strawhouse Pattern</em> <p>When you use CZMQ, all authentication happens through a <tt>zauth</tt> object, aka an &quot;authenticator&quot;. In the Strawhouse code we create an authenticator, we enable verbose tracing (during development, at least), and we whitelist one address. Then we do the same work as Grasslands, and finally we destroy the authenticator:</p> <div class="code"> <pre><code>zauth_t *auth = zauth_new (ctx); zauth_set_verbose (auth, true); zauth_allow (auth, &quot;127.0.0.1&quot;); ... zauth_destroy (&amp;auth);</code></pre></div> <p>Internally, the authenticator talks to libzmq across <a href="http://rfc.zeromq.org/spec:27">a protocol called ZAP</a>, aka RFC 27. Every single time a client tries to connect to a server, libzmq asks the ZAP handler (the authenticator), if there is one installed, to allow or deny the connection.</p> <p>We tell libzmq that the server socket is in fact a &quot;server&quot; in the sense that it authenticates clients, by using this call:</p> <div class="code"> <pre><code>zsocket_set_zap_domain (server, &quot;global&quot;);</code></pre></div> <p>The ZAP <em>domain</em> concept lets you define authentication groups. For instance a set of server sockets could say, &quot;We're in a domain called &quot;test&quot; and we only accept localhost IP addresses&quot;. CZMQ doesn't implement domains yet, and the &quot;global&quot; domain we use here has no significance at all. Remember that in this example we're using the NULL security mechanism, and by default libzmq just accepts NULL connections, period. But the simple fact of telling libzmq, &quot;Please set domain X on this socket (with the default NULL security mechanism)&quot; will cause it to act as a server, and call the ZAP handler for every client request.</p> <p>You can mix different kinds of security in one application, by using different sockets, and then configuring each security mechanism separately in the authenticator. So it will handle PLAIN in one way, CURVE another way, and so on.</p> <p>Now, to CZMQ's IP address filtering. This uses whitelisting and blacklisting, and works thus:</p> <ul> <li>You can whitelist one or more addresses, or blacklist one or more addresses. We do this through the zauth_allow() and zauth_deny() calls, rather than loading external files.</li> </ul> <ul> <li>The whitelist or blacklist applies to all requests that the authenticator gets from libzmq. That is, any NULL socket with a ZAP domain set, any PLAIN server socket, or any CURVE server socket, on that ZeroMQ context.</li> </ul> <ul> <li>If you have a whitelist (one or more addresses), that means, &quot;reject any address that's not in the whitelist&quot;. Think of a private party, a very large bouncer, and a sheet of paper with names on it. <em>&quot;Sorry, buddy, you're not on the list. Please move out of the way.&quot;</em></li> </ul> <ul> <li>If you have a blacklist (one or more addresses), that means, &quot;reject any address that's in the blacklist&quot;. Think of a public function with a couple of very large bouncers and a sheet of paper with names on it. <em>&quot;Hey buddy, didn't we tell you to never show your face here again?</em>&quot; You won't use both a whitelist and a blacklist, unless you want to make the bouncers confused, and angry.</li> </ul> <ul> <li>If not denied, and the security mechanism is NULL, then the connection is allowed.</li> </ul> <ul> <li>If not denied, and the mechanism is PLAIN or CURVE, then the authenticator carries on with its checking. So perhaps you're on the whitelist, or not on the blacklist, but now we need to see some identification, please.</li> </ul> <p>So in our example, where we allow &quot;127.0.0.1&quot;, we effectively deny every other client address.</p> <h2><span>The Woodhouse Pattern</span></h2> <p>Next, let's see how to do username and password authentication. Here is the full example:</p> <div class="code"> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Woodhouse Pattern<br /> <span style="white-space: pre-wrap;">//</span><br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>It may keep some malicious people out but all it takes is a bit<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>of network sniffing, and they'll be able to fake their way in.</span></span></p> <p><span style="color:#BC7A00">#include &lt;czmq.h&gt;</span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create context and start authentication engine</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zauth_t</span> <span style="color:#666666">*</span>auth <span style="color:#666666">=</span> zauth_new (ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_set_verbose (auth, <span style="color:#008000">true</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_allow (auth, <span style="color:#BA2121">&quot;127.0.0.1&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Tell the authenticator how to handle PLAIN requests</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_configure_plain (auth, <span style="color:#BA2121">&quot;*&quot;</span>, <span style="color:#BA2121">&quot;passwords&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and bind server socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>server <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PUSH);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_plain_server (server, <span style="color:#666666">1</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (server, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:9000&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and connect client socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>client <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PULL);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_plain_username (client, <span style="color:#BA2121">&quot;admin&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_plain_password (client, <span style="color:#BA2121">&quot;secret&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (client, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>127.0.0.1:9000&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send a single message from server to client</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (server, <span style="color:#BA2121">&quot;Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>message <span style="color:#666666">=</span> zstr_recv (client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (streq (message, <span style="color:#BA2121">&quot;Hello&quot;</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (message);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (<span style="color:#BA2121">&quot;Woodhouse test OK&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_destroy (<span style="color:#666666">&amp;</span>auth);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>woodhouse.c: Woodhouse Pattern</em> <p>Setting up the authenticator and the whitelist is the same as in Strawhouse, and I won't explain that again. The new API calls happen in three places in the code:</p> <div class="code"> <pre><code>// Tell the authenticator how to handle PLAIN requests zauth_configure_plain (auth, &quot;*&quot;, &quot;passwords&quot;); ... // Before binding the server zsocket_set_plain_server (server, 1); ... // Before connecting the client zsocket_set_plain_username (client, &quot;admin&quot;); zsocket_set_plain_password (client, &quot;secret&quot;);</code></pre></div> <p>Bear this in mind: you have to configure a socket before doing a _bind or _connect on it. If you run the Woodhouse example without a password file, it'll never complete. Since we enabled tracing, you'll see it print out this:</p> <div class="code"> <pre><code>I: PASSED (whitelist) address=127.0.0.1 I: DENIED (PLAIN) username=admin password=secret</code></pre></div> <p>The message in fact repeats because ZeroMQ re-tries the connection over and over. We mught change this behavior but it's not significant here. Let's create a password file, &quot;passwords&quot;, in the current directory, with some entries, one per line:</p> <div class="code"> <pre><code>guest=guest tourist=1234 admin=secret</code></pre></div> <p>Then run the Woodhouse example again, and it'll print this:</p> <div class="code"> <pre><code>I: PASSED (whitelist) address=127.0.0.1 I: ALLOWED (PLAIN) username=admin password=secret Woodhouse test OK</code></pre></div> <h2><span>The Stonehouse Pattern</span></h2> <p>Plain text is what it is. Anyone with half a malicious intent can sniff traffic and impersonate real clients, and make a mockery of your so-called security. That may be fine, or it may be a problem. The next level up is Stonehouse, which changes the game somewhat. Here's the example code:</p> <div class="code"> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Stonehouse Pattern<br /> <span style="white-space: pre-wrap;">//</span><br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Where we allow any clients to connect, but we promise clients<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>that we are who we claim to be, and our conversations won't be<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>tampered with or modified, or spied on.</span></span></p> <p><span style="color:#BC7A00">#include &lt;czmq.h&gt;</span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create context and start authentication engine</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zauth_t</span> <span style="color:#666666">*</span>auth <span style="color:#666666">=</span> zauth_new (ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_set_verbose (auth, <span style="color:#008000">true</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_allow (auth, <span style="color:#BA2121">&quot;127.0.0.1&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Tell the authenticator how to handle CURVE requests</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_configure_curve (auth, <span style="color:#BA2121">&quot;*&quot;</span>, CURVE_ALLOW_ANY);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We need two certificates, one for the client and one for</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>the server. The client must know the server's public key</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>to make a CURVE connection.</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>client_cert <span style="color:#666666">=</span> zcert_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>server_cert <span style="color:#666666">=</span> zcert_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>server_key <span style="color:#666666">=</span> zcert_public_txt (server_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and bind server socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>server <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PUSH);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_apply (server_cert, server);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_curve_server (server, <span style="color:#666666">1</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (server, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:9000&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and connect client socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>client <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PULL);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_apply (client_cert, client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_curve_serverkey (client, server_key);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (client, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>127.0.0.1:9000&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send a single message from server to client</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (server, <span style="color:#BA2121">&quot;Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>message <span style="color:#666666">=</span> zstr_recv (client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (streq (message, <span style="color:#BA2121">&quot;Hello&quot;</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (message);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (<span style="color:#BA2121">&quot;Stonehouse test OK&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_destroy (<span style="color:#666666">&amp;</span>client_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_destroy (<span style="color:#666666">&amp;</span>server_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_destroy (<span style="color:#666666">&amp;</span>auth);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>stonehouse.c: Stonehouse Pattern</em> <p>Stonehouse starts with a single call to the authenticator that switches on the CURVE_ALLOW_ANY feature:</p> <div class="code"> <pre><code>zauth_configure_curve (auth, &quot;*&quot;, CURVE_ALLOW_ANY);</code></pre></div> <p>Here we do that for the domain &quot;*&quot;, meaning all domains. Recall that CZMQ doesn't deal with domains yet, so if you use Stonehouse on one server socket, it will apply to all server sockets in the same context.</p> <p>Now, let's talk about certificates. For any CURVE security you need a &quot;long-term public / secret keypair&quot; for the client, and for the server. CZMQ wraps up a keypair along with metadata (a name, email address, etc.) as a &quot;certificate&quot;, which can be an in-memory object, or a disk file. Here is the explanation from the zcert class:</p> <blockquote> <p>The zcert class provides a way to create and work with security certificates for the ZMQ CURVE mechanism. A certificate contains a public + secret key pair, plus metadata. It can be used as a temporary object in memory, or persisted to disk. On disk, a certificate is stored as two files. One is public and contains only the public key. The second is secret and contains both keys. The two have the same filename, with the secret file adding &quot;_secret&quot;. To exchange certificates, send the public file via some secure route. Certificates are not signed but are text files that can be verified by eye.</p> </blockquote> <blockquote> <p>Certificates are stored in the ZPL (ZMQ RFC 4) format. They have two sections, &quot;metadata&quot; and &quot;curve&quot;. The first contains a list of 'name = value' pairs, one per line. Values may be enclosed in quotes. The curve section has a 'public-key = keyvalue' and, for secret certificates, a 'secret-key = keyvalue' line. The keyvalue is a Z85-encoded CURVE key.&quot;</p> </blockquote> <p>What you would do in practice is generate certificates up-front (and CZMQ provides a simple tool to do this, in addons/makecert), and then put them carefully on each node in your network. It's like handing out neat little membership cards for an exclusive club, up front. Makes life easier for guests and security alike.</p> <p>In the Ironhouse example we'll see how to work with &quot;real&quot; certificates on disk, using a so-called &quot;certificate store&quot;. However for this example, we can generate certificates on-the-fly, in memory, and pretend we got them from disk.</p> <p>We need a client certificate, a server certificate, and then we also have to pass the server's public key to the client. This is the total setup to use the Stonehouse pattern. CZMQ provides a zcert class that generates a new certificate, and which we can &quot;apply&quot; to a socket in order to enable it for CURVE security. Finally, we have to tell the client socket what our server public key is. Here are the relevant API calls:</p> <div class="code"> <pre><code>// Generate certificates at runtime, since this is a test zcert_t *client_cert = zcert_new (); zcert_t *server_cert = zcert_new (); char *server_key = zcert_public_txt (server_cert); ... // Before binding the server zcert_apply (server_cert, server); zsocket_set_curve_server (server, 1); ... // Before connecting the client zcert_apply (client_cert, client); zsocket_set_curve_serverkey (client, server_key); ... // Destroy these in-memory objects when done zcert_destroy (&amp;client_cert); zcert_destroy (&amp;server_cert);</code></pre></div> <p>The zcert_new() call generates a public/secret key pair. We can ornament that with metadata, e.g. name, email, and organization, which can be helpful when managing certificates. Metadata doesn't play any role in authentication however.</p> <h2><span>The Ironhouse Pattern</span></h2> <p>Now, let's explore full authentication of clients. I call this the Ironhouse pattern, just to remind us that security is never total or perfect. It's always about cost. Even an iron house may have holes in the floor, or the roof, and your security is only as good as the systems it runs on. If you run Ironhouse on a box with an insecure or outdated operating system, don't expect privacy.</p> <p>Here's the Ironhouse example:</p> <div class="code"> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Ironhouse Pattern<br /> <span style="white-space: pre-wrap;">//</span><br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Security doesn't get any stronger than this. An attacker is going to<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>have to break into your systems to see data before/after encryption.</span></span></p> <p><span style="color:#BC7A00">#include &lt;czmq.h&gt;</span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create context and start authentication engine</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zauth_t</span> <span style="color:#666666">*</span>auth <span style="color:#666666">=</span> zauth_new (ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_set_verbose (auth, <span style="color:#008000">true</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_allow (auth, <span style="color:#BA2121">&quot;127.0.0.1&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Tell authenticator to use the certificate store in .curve</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_configure_curve (auth, <span style="color:#BA2121">&quot;*&quot;</span>, <span style="color:#BA2121">&quot;.curve&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We'll generate a new client certificate and save the public part</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>in the certificate store (in practice this would be done by hand</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>or some out-of-band process).</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>client_cert <span style="color:#666666">=</span> zcert_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsys_dir_create (<span style="color:#BA2121">&quot;.curve&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_set_meta (client_cert, <span style="color:#BA2121">&quot;name&quot;</span>, <span style="color:#BA2121">&quot;Client test certificate&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_save_public (client_cert, <span style="color:#BA2121">&quot;.curve/testcert.pub&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Prepare the server certificate as we did in Stonehouse</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>server_cert <span style="color:#666666">=</span> zcert_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>server_key <span style="color:#666666">=</span> zcert_public_txt (server_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and bind server socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>server <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PUSH);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_apply (server_cert, server);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_curve_server (server, <span style="color:#666666">1</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (server, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:9000&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create and connect client socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>client <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PULL);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_apply (client_cert, client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_curve_serverkey (client, server_key);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (client, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>127.0.0.1:9000&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send a single message from server to client</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (server, <span style="color:#BA2121">&quot;Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>message <span style="color:#666666">=</span> zstr_recv (client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (streq (message, <span style="color:#BA2121">&quot;Hello&quot;</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (message);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (<span style="color:#BA2121">&quot;Ironhouse test OK&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_destroy (<span style="color:#666666">&amp;</span>client_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_destroy (<span style="color:#666666">&amp;</span>server_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_destroy (<span style="color:#666666">&amp;</span>auth);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>ironhouse.c: Ironhouse Pattern</em> <p>Ironhouse is very similar to Stonehouse except it uses a &quot;certificate store&quot;. That is a directory somewhere on the server's file system that contains a set of client public certificates. This is the API we use:</p> <div class="code"> <pre><code>// Tell authenticator to use the certificate store in .curve zauth_configure_curve (auth, &quot;*&quot;, &quot;.curve&quot;); ... // Stick the client public certificate into the directory zcert_t *client_cert = zcert_new (); zcert_save_public (client_cert, &quot;.curve/testcert.pub&quot;);</code></pre></div> <p>For the client, nothing changes — it's the same code as for Stonehouse, as you'd expect. If this wasn't clear already, the zauth object belongs to the server, not the client.</p> <p>A word about certificate stores. This is a CZMQ concept, and implemented by the zcertstore class. Normally you won't use that class directly, but like this example, allow the authenticator to manage it. All we do is (a) tell the authenticator what directory will hold certificates, and then make sure our clients' public certificates end up safely there.</p> <p>In practice a server application will be a long-running process, so the certificate store reloads itself automatically if there is a change. This means we can copy new certificates into it at any time, to allow new clients, or remove certificates to reject clients.</p> <p>Certificate filenames don't matter. Here we use &quot;testcert.pub&quot; but in practice I'd use a filename which is based of the certificate public key, for instance, to ensure it's unique. In our example we create the directory, and add some meta data, before saving the certificate:</p> <div class="code"> <pre><code>// Create the directory zsys_dir_create (&quot;.curve&quot;); zcert_set_meta (client_cert, &quot;name&quot;, &quot;Client test certificate&quot;); zcert_save_public (client_cert, &quot;.curve/testcert.pub&quot;);</code></pre></div> <p>When you save a certificate using the zcert_save_public (or zcert_save) method, it looks like this:</p> <div class="code"> <pre><code># **** Generated on 2013-09-19 21:25:34 by CZMQ **** # ZeroMQ CURVE Public Certificate # Exchange securely, or use a secure mechanism to verify the contents # of this file after exchange. Store public certificates in your home # directory, in the .curve subdirectory. metadata name = &quot;Client test certificate&quot; curve public-key = &quot;I7[{YV4[}q[9a)]b&amp;d&gt;bisoT]UXa/7b$Tp:6yoyq&quot;</code></pre></div> <p>In own applications I'm using $HOME/.curve to hold certificates, as zcert recommends, but you can put them anywhere. Some guidelines do apply:</p> <ul> <li>A certificate produced by makecert has a secret and a public file. Never share the secret file with anyone.</li> </ul> <ul> <li>When you transfer public certificates, use a secure route. If an attacker can modify this data without you knowing about it, they can construct a man-in-the-middle attack.</li> </ul> <ul> <li>For the same reason, make sure public certificates are not writeable by anyone except the current user.</li> </ul> <h2><span>The Ironhouse Pattern, Model 2</span></h2> <p>When you read the examples so far, you might be tempted to copy the code for your own applications. However it's not meant for that. It doesn't have a clean separation into client and server, and doesn't do any error checking. Here's a reworking of the Ironhouse example that is much more explicit. It's also twice the amount of code:</p> <div class="code"> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Ironhouse Pattern<br /> <span style="white-space: pre-wrap;">//</span><br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>This is exactly the same example but broken into two threads<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>so you can better see what client and server do, separately.</span></span></p> <p><span style="color:#BC7A00">#include &lt;czmq.h&gt;</span></p> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The client task runs in its own context, and receives the<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>server public key as an argument.</span></span></p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span> <span style="color:#666666">*</span><br /> <span style="color:#0000FF">client_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Load our persistent certificate from disk</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>client_cert <span style="color:#666666">=</span> zcert_load (<span style="color:#BA2121">&quot;client_cert.txt&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (client_cert);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create client socket and configure it to use full encryption</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>client <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PULL);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_apply (client_cert, client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_curve_serverkey (client, (<span style="color:#B00040">char</span> <span style="color:#666666">*</span>) args);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zsocket_connect (client, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>127.0.0.1:9000&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (rc <span style="color:#666666">==</span> <span style="color:#666666">0</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Wait for our message, that signals the test was successful</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>message <span style="color:#666666">=</span> zstr_recv (client);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (streq (message, <span style="color:#BA2121">&quot;Hello&quot;</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (message);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (<span style="color:#BA2121">&quot;Ironhouse test OK&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Free all memory we used</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_destroy (<span style="color:#666666">&amp;</span>client_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#008000">NULL</span>;<br /> }</p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span> <span style="color:#666666">*</span><br /> <span style="color:#0000FF">server_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zctx_t</span> <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start the authenticator and tell it do authenticate clients</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>via the certificates stored in the .curve directory.</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zauth_t</span> <span style="color:#666666">*</span>auth <span style="color:#666666">=</span> zauth_new (ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (auth);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_set_verbose (auth, <span style="color:#008000">true</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_allow (auth, <span style="color:#BA2121">&quot;127.0.0.1&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_configure_curve (auth, <span style="color:#BA2121">&quot;*&quot;</span>, <span style="color:#BA2121">&quot;.curve&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create server socket and configure it to use full encryption</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>server <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_PUSH);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (server);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_apply ((<span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>) args, server);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_curve_server (server, <span style="color:#666666">1</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zsocket_bind (server, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:9000&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (rc <span style="color:#666666">!=</span> <span style="color:#666666">-</span><span style="color:#666666">1</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send our test message, just once</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (server, <span style="color:#BA2121">&quot;Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zclock_sleep (<span style="color:#666666">200</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Free all memory we used</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zauth_destroy (<span style="color:#666666">&amp;</span>auth);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#008000">NULL</span>;<br /> }</p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create the certificate store directory and client certs</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>client_cert <span style="color:#666666">=</span> zcert_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zsys_dir_create (<span style="color:#BA2121">&quot;.curve&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (rc <span style="color:#666666">==</span> <span style="color:#666666">0</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_set_meta (client_cert, <span style="color:#BA2121">&quot;name&quot;</span>, <span style="color:#BA2121">&quot;Client test certificate&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_save_public (client_cert, <span style="color:#BA2121">&quot;.curve/testcert.pub&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>rc <span style="color:#666666">=</span> zcert_save (client_cert, <span style="color:#BA2121">&quot;client_cert.txt&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (rc <span style="color:#666666">==</span> <span style="color:#666666">0</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_destroy (<span style="color:#666666">&amp;</span>client_cert);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Create the server certificate</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">zcert_t</span> <span style="color:#666666">*</span>server_cert <span style="color:#666666">=</span> zcert_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Now start the two detached threads; each of these has their</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>own ZeroMQ context.</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zthread_new (server_task, server_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zthread_new (client_task, zcert_public_txt (server_cert));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>As we're using detached threads this is the simplest way //</em><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>to ensure they both end, before we exit the process. 200<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>milliseconds should be enough for anyone. In real code,<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>you would use messages to synchronize threads.//</span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zclock_sleep (<span style="color:#666666">200</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Free the memory we used</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zcert_destroy (<span style="color:#666666">&amp;</span>server_cert);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>ironhouse2.c: Ironhouse Pattern, model 2</em> <p>Here we see how to save and load client certificates from disk, to create truly persistent certificates:</p> <div class="code"> <pre><code>zcert_t *client_cert = zcert_new (); zcert_save (client_cert, &quot;client_cert.txt&quot;); zcert_destroy (&amp;client_cert);</code></pre></div> <p>And then, in a different place and time, or at least a separate thread:</p> <div class="code"> <pre><code>// Load our persistent certificate from disk zcert_t *client_cert = zcert_load (&quot;client_cert.txt&quot;);</code></pre></div> <h2><span>Wrapping Up</span></h2> <p>OK, that's enough code. After half a dozen examples, we start to get code blindness. What is striking however is how short the code examples are, even in C. For me, this is success.</p> <p>There's one last thing I want to discuss about security, which is the constant harping on about &quot;server&quot; and &quot;client&quot;, which you may know are not ZeroMQ native concepts at all. The closest we get in ZeroMQ is having one side binding to an endpoint, and the other side connecting to it.</p> <p>When using the PLAIN or CURVE security mechanisms (wood, stone, or iron), you can bind the client and connect the server. You can try this in stonehouse.c for example. Simply switch the bind and connect statements (change the socket arguments :) and observe that it still works. The server still authenticates the client.</p> <p>You'll get the best results by typing the code, because muscle memory is a fantastic thing for programming. But if you're in a hurry, <a href="https://github.com/zeromq/czmq">it is in the CZMQ project</a>, in the examples/security directory. These examples are licensed under MIT/X11 so you can reuse the code in your own applications.</p> <p>Let me know how you get on. Comment below, or come to the <a href="http://zeromq.org/docs:mailing-lists">zeromq-dev mailing list</a>. If you need commercial support in using these new security tools, or you're an open source project that wants to use them, drop me an email at <span class="wiki-email">moc.xitami|hp#moc.xitami|hp</span> and tell me your use case.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:48</guid>
				<title>Using ZeroMQ Security (part 1)</title>
				<link>http://hintjens.wikidot.com/blog:48</link>
				<description>

&lt;p&gt;In this series of articles I&#039;ll explain how to use the new ZeroMQ security layers in your applications. The example we&#039;ll make is a chat application that provides unbreakable strong security. In this first article, I&#039;ll explain more about ZeroMQ&#039;s security technology, how it works, and why we chose it. (&lt;a href=&quot;http://hintjens.wikidot.com/blog:49&quot;&gt;Read part 2.&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 12 Sep 2013 09:17:55 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>In this series of articles I'll explain how to use the new ZeroMQ security layers in your applications. The example we'll make is a chat application that provides unbreakable strong security. In this first article, I'll explain more about ZeroMQ's security technology, how it works, and why we chose it. (<a href="http://hintjens.wikidot.com/blog:49">Read part 2.</a>)</p> <h2><span>The Case for Privacy</span></h2> <p>The summer of 2013 was when privacy on the Internet died. Or rather, when our belief in privacy died, because the surveillance of our phone calls, emails, web searches, and chats has been going on for many years, if not since the start of the telegraph era.</p> <p>Privacy is a cost issue. An organization can secure its data centers from surveillance (by spies of all colors, whether they are foreign intelligence services, competitors, or criminals) by building its own physical networks and isolating these from the public Internet. However that is extraordinarily costly. More typically, we'll use virtual private networks (VPNs) to create secure lines that cross public networks.</p> <p>VPNs are not reliably secure, however. They use long term keys that can be broken. They are complex to configure and to upgrade. The often use aging algorithms like RC4 <a href="http://www.theregister.co.uk/2013/09/06/nsa_cryptobreaking_bullrun_analysis/">that are considered crackable</a>.</p> <p>Even SSL/TLS <a href="http://www.techdirt.com/articles/20130910/10470024468/flying-pig-nsa-is-running-man-middle-attacks-imitating-googles-servers.shtml#addyourcomment">are not immune</a> from attack. The NSA themselves point out that the mainstream cryptography <a href="http://www.nsa.gov/business/programs/elliptic_curve.shtml">is over 20 years old</a>, and state that &quot;the best assured group of new public key techniques is built on the arithmetic of elliptic curves.&quot;</p> <p>Without the shield of cheap, trustable privacy, an organization cannot safely use the public Internet. What the NSA can break today, any competitor or foreign intelligence service can break tomorrow. In our connected world, this throws a pool of ice cold water over the growth of low-friction Internet commerce.</p> <h2><span>Goals for ZeroMQ's Security Layers</span></h2> <p>Just as ZeroMQ brought us cheap, standardized connectivity for distributed systems, our goals with the security layers (which I'll explain in a minute) are to bring cheap, standardized privacy and authentication for distributed systems. The focus here is on cost. Cryptography has not stood still since the 1970s and there are many excellent, strong security options. However they remain costly to learn, understand, and safely use.</p> <p>Here is our shortlist of goals:</p> <ul> <li><em>It must be very simple to use, and impossible to get wrong</em>. Complexity is the number one risk with cryptography and the number one vulnerability. Every additional option is a way to get it wrong and end up with an insecure system.</li> </ul> <ul> <li><em>It must be fast enough for real work</em>. If security makes a system too slow to use, people will switch it off, because the pragmatic need of being able to work today beats the risk of intrusion tomorrow.</li> </ul> <ul> <li><em>It must be based on standardized protocols</em>, so that it can be re-implemented by any team, verified independently, and improved outside of the software stack.</li> </ul> <ul> <li><em>It must have free and open source implementations</em>, so that the code can be inspected and fixed. One cannot trust a closed-source security stack, given the risk of secret backdoors.</li> </ul> <ul> <li><em>It must be free of patent risk</em>, so that it cannot be blocked on grounds of intellectual property violations.</li> </ul> <ul> <li><em>It must work with all ZeroMQ socket types</em>, and more generally, be interoperable with clear text messaging. A typical architecture will use clear text for internal messages, and security on external traffic.</li> </ul> <ul> <li><em>It must be built-in to the core libzmq library</em>, so that it is available to all language bindings. Full-native stacks like JeroMQ should be able to re-implement the security protocols.</li> </ul> <p>We started working on this in March of 2013, and the first formal publication will be in the forthcoming ZeroMQ/4.0.0 release. You can always get the latest version from the ZeroMQ GitHub project.</p> <h2><span>How ZeroMQ Security Works</span></h2> <p>The security architecture is broken into several layers:</p> <ul> <li>A new wire protocol, <a href="http://zmtp.org">ZMTP 3.0</a>, that adds a security handshake to all ZeroMQ connections.</li> </ul> <ul> <li>A new security protocol, <a href="http://curvezmq.org">CurveZMQ</a>, that implements &quot;perfect forward security&quot; between two ZeroMQ peers over a TCP connection. I'll explain CurveZMQ below.</li> </ul> <ul> <li>A set of security mechanisms for ZMTP: NULL, PLAIN, and CURVE, each described by their own RFCs. NULL is essentially what we had before. PLAIN allows simple username and password authentication. CURVE implements the CurveZMQ protocol.</li> </ul> <ul> <li>An extended API for libzmq that lets you choose and configure the security mechanism for any socket. The default is NULL. You can then upgrade the socket to PLAIN or CURVE, either as a client (that connects securely to one server), or a server (which authenticates any number of clients).</li> </ul> <ul> <li><a href="http://rfc.zeromq.org/spec:27">A protocol (ZAP)</a> that lets you install arbitrary authentication servers. ZeroMQ lets you choose how you authenticate clients, be it via configuration files, LDAP, databases, etc.</li> </ul> <ul> <li>Finally, a separate security library, <a href="https://github.com/zeromq/libcurve">Curve</a>, that implements CurveZMQ on top of ZeroMQ. Curve is a reference implementation for the CurveZMQ protocol, and a way to get that functionality on older versions of ZeroMQ. It will work with ZeroMQ/2.x and ZeroMQ/3.x (but not interoperate with the ZeroMQ/4.x CURVE mechanism, that works at a different level).</li> </ul> <p>Let's walk through how we do secure PUB-SUB from one publisher to a number of subscribers, using the CURVE mechanism:</p> <ul> <li>We generate a long term keypair for the publisher. ZeroMQ provides a tool (curve_keygen) to do this. We store the resulting keypair safely.</li> </ul> <ul> <li>We manually distribute the public part of the keypair. This is a short text string. ZeroMQ does not do key exchange.</li> </ul> <ul> <li>If we want to authenticate subscribers, we generate a keypair for each subscriber, store the public+secret keypair safely at each subscriber, and collect all public subscriber keys on the publisher.</li> </ul> <ul> <li>Now, we can create a PUB socket and configure it with the long term keypair, and tell ZeroMQ that it is a server. This requires three zmq_setsockopt calls.</li> </ul> <ul> <li>We can then create any number of SUB sockets, and configure each one with its own keypair, and the server's public key. Again, three calls to zmq_setsockopt.</li> </ul> <ul> <li>We then bind the PUB socket, and connect the SUB sockets as usual.</li> </ul> <ul> <li>The ZeroMQ messaging API is unchanged. We send and recv messages as before.</li> </ul> <p>One aspect that surprises some people is that one socket can have exactly one security level. You cannot have, for instance, PLAIN and CURVE subscribers connected to the same publisher. This would be technically feasible but would add extra work to applications to check the security level of every incoming message. It would make it easy to &quot;get it wrong&quot;.</p> <h2><span>The Curve Story</span></h2> <p>Elliptic curve cryptography is a controversial topic. It has the reputation of being &quot;backdoored&quot; by the NSA, and heavily patented. There is no single curve, but an infinite number, and different curves have different strengths and weaknesses. Some of the &quot;official&quot; curves proposed by the NIST are suspect.</p> <p>We use <a href="http://cr.yp.to/ecdh.html">Curve25519</a> as designed by Daniel J. Berstein, which is the basis for the <a href="http://nacl.cace-project.eu/features.html">NaCl cryptographic library</a>, more widely used as <a href="https://github.com/jedisct1/libsodium">libsodium</a>.</p> <p>Curve25519 together with the other algorithms used in NaCl has some attractive features:</p> <ul> <li>It is fast.</li> <li>It <a href="http://cr.yp.to/ecdh/patents.html">has no known patent issues</a>.</li> <li>It is considered strong.</li> </ul> <p>Curve25519 provides encryption and authentication with 256-bit keys, equivalent to 3072-bit RSA keys.</p> <p>This isn't sufficient guard against the simplest threat, where an attacker records encrypted data today, and then decrypts that tomorrow, after getting the keys by force, subterfuge, or warrant.</p> <p>To prevent that, we need &quot;perfect forward security&quot;, in which the two peers create temporary session keys and exchange those safely using the long-term keys. When the session is over, they discard their keys, and the encrypted data is then unreadable by anyone.</p> <p>D. J. Bernstein developed the <a href="http://curvecp.org">CurveCP</a> protocol for secure networking over UDP, part of which was a secure handshake that provides perfect forward security using Curve25519.</p> <p>The ZeroMQ CurveZMQ protocol is essentially a fork of CurveCP, adapted for use over TCP, and written as a single RFC.</p> <p>Clients and servers have long-term permanent keys, and for each connection, they create and securely exchange short-term transient keys. Each key is a public/secret keypair, following the elliptic curve security model.</p> <p>To start a secure connection the client needs the server permanent public key. It then generates a transient key pair and sends a HELLO command to the server that contains its short term public key. The HELLO command is worthless to an attacker; it doesn't identify the client.</p> <p>The server, when it gets a HELLO, generates its own short term key pair (one connection uses four keys in total), and encodes this new private key in a &quot;cookie&quot;, which it sends back to the client as a WELCOME command. It also sends its short term public key, encrypted so only the client can read it. It then discards this short term key pair.</p> <p>At this stage, the server hasn't stored any state for the client. It has generated a keypair, sent that back to the client in a way only the client can read, and thrown it away.</p> <p>The client comes back with an INITIATE command that provides the server with its cookie back, and the client permanent public key, encrypted as a &quot;vouch&quot; so only the server can read it. As far as the client is concerned, the server is now authenticated, so it can also send back metadata in the command.</p> <p>The server reads the INITIATE and can now authenticate the client permanent public key. It also unpacks the cookie and gets its short term key pair for the connection. As far as the server is now concerned, the client is now authenticated, so the server can send its metadata safely. Both sides can then send messages and commands.</p> <p>This handshake provides a number of protections but mainly, <em>perfect forward security</em> (you cannot crack data encrypted using the short term keys even if you record it, and then later get access to the permanent keys) and <em>protection of client identity</em> (the client permanent public key is not sent in clear-text).</p> <h2><span>Multilayer Security Using Libcurve</span></h2> <p>ZeroMQ's built-in Curve security can protect only one hop. For a B-to-C use-case this is ideal, and acts as a replacement for TLS/SSL, without the certificate authorities, but with the added cost of pre-distribution of public keys.</p> <p>For C-to-B-to-C cases however, it is not sufficient, just as TLS/SSL is not sufficient. The cloud in the middle gets unencrypted traffic, and surveillance at that point is trivial.</p> <p>To solve this we need security at a higher layer (instead of, or in addition to, the transport-layer security).</p> <p>In effect this means encrypting messages <em>before</em> passing them to ZeroMQ, and then decrypting them after receiving them from ZeroMQ. The same requirement for perfect forward security applies, otherwise the data is vulnerable to key theft attacks.</p> <p>With our security architecture, we use the Curve library (libcurve) to handle this higher layer. Curve provides both low-level codecs (to encrypt and decrypt) messages, and high-level &quot;virtual sockets&quot; (that act like ZeroMQ sockets but do security behind the scenes).</p> <h2><span>Coming Up</span></h2> <p>Security is complex, but if done right, will protect your business secrets from attackers. In my next article I'll start show example code that does secure messaging, over ZeroMQ. If you want to contact me directly about using ZeroMQ's security in your architectures, email me at <span class="wiki-email">moc.xitami|hp#moc.xitami|hp</span>.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:46</guid>
				<title>Charlie and the X-ray Factory</title>
				<link>http://hintjens.wikidot.com/blog:46</link>
				<description>

&lt;p&gt;Last week I had the pleasure of visiting not one major European physics research facility, but two. My first stop was at ESRF in Grenoble, then I went to visit CERN in Geneva. Both these organizations are moving to use ZeroMQ for their control systems. In this article I&#039;ll explain what that means.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 07 Jul 2013 12:26:14 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Last week I had the pleasure of visiting not one major European physics research facility, but two. My first stop was at ESRF in Grenoble, then I went to visit CERN in Geneva. Both these organizations are moving to use ZeroMQ for their control systems. In this article I'll explain what that means.</p> <h2><span>First, the Physics</span></h2> <p>I'm not a physicist, but my kind hosts &#8212; Emmanuel Taurel at ESRF, and then Wojtek Sliwinski at CERN &#8212; explained the basics to me. ESRF and CERN both have large circular accelerators, though &quot;large&quot; is relative. ESRF's is the size of a small airport. CERN's is the size of a small town. They also have linear accelerators (LINACs) that act as injectors for the larger circular ones. Actually CERN has a dozen different accelerators, built over time.</p> <p>The major difference &#8212; from the physics point of view, not the software &#8212; is that ESRF accelerates beams of electrons, while CERN accelerates beams of protons, because the physics experiments they're conducting on both sites are very different.</p> <p>ESRF scientists basically want to shoot streams of X-rays at samples to get information about their molecular structure. I assume that it's like shining a very bright light at them.</p> <p>How do you get streams of X-rays? It turns out that if you take electron beams and bend them (or perhaps it's twist them, I'm not sure), they emit X-rays along the direction they wanted to go in. I've not tried this at home, but it makes sense.</p> <p>So ESRF shoots electron beams (from very big cathode ray guns, like we used to have in TVs) into a ring and speeds them up, getting them to go faster and faster, and as they spin around, they emit X-rays where they get bent by the massive magnets. There are several kinds of magnets, the size of fridges. The X-rays are guided down with more magnets, filtered and bounced off mirrors, and whatnot, and focused on the samples, where high-speed cameras record the results. The ring carries forty independent beams of electrons, and along the ESRF ring there are forty corresponding experiment rooms.</p> <p>In ESFR's X-ray factory, therefore, you have a whole set of devices &#8212; hundreds &#8212; that create, steer, twist, bend, and focus these electrons and X-rays. As there are forty independent beams, they manage each beam more or less separately, though I've no idea how they do this. Magic, I assume.</p> <p>The control room is basically filled with large panels that show the status of the whole machine as it operates. From these panels, scientists can tune their beams, pump in more electrons, focus them, get readings, and so on, through an impressive graphical user interface. It is a &quot;drive by wire&quot; control system, which was innovative when it came along, for before that, scientists would literally tune their magnets and mirrors by hand.</p> <p>Now, at CERN, the physics are very different. CERN's mission is to create black holes, or at least very large holes in the ground, because their largest ring, the <a href="https://en.wikipedia.org/wiki/Large_Hadron_Collider">Large Hadron Collider</a> or LHC, is 27km around. You can't see it except from the buildings on the surface, dotted around its position.</p> <p>At CERN, the X-rays are a nuisance. What the LHC does is create speeding clouds of protons, which are positively-charged particles with mass (electrons being negatively-charged wavelets that sometimes act as particles but with a tiny mass compared to protons). They speed these clouds up faster and faster, in two beams, one rotating clockwise, and one anti-clockwise. They then smash these two clouds into each other, simulating the Big Bang at the origin of the Universe, and seeing what the heck emerges from that.</p> <p>The CERN experiments are basically massive collectors, and the LHC has four main ones, and three smaller ones. We visited the largest, ATLAS, buried underground. ATLAS is a &quot;general purpose&quot; collector, meaning it looks for many kinds of collisions. This is what makes it so large. The special purpose collectors focus on just one type of collision and can be much more compact.</p> <p>So the experiments at ESRF and CERN are entirely different but the two control systems follow a similar pattern. It's these two control systems that both ESRF and CERN are rewriting to take advantage of state-of-the-art technology in messaging, namely ZeroMQ.</p> <h2><span>Second, the Architecture</span></h2> <p>The ESRF control software is called <a href="http://www.tango-controls.org/">Tango</a>, and is a collaborative effort between nine different research institutes. It's open source along the cathedral model (whereas ZeroMQ is a work of the bazaar). Tango used CORBA for its messaging and is now moving to ZeroMQ. Tango has the makings of a widely-used product, even a general-purpose industrial control system, <a href="http://en.wikipedia.org/wiki/SCADA,">or SCADA</a>, since it is essentially simple and already used in multiple institutes.</p> <p>The CERN control software (the &quot;middleware&quot;) is a different animal. It's much larger and more complex, reflecting the much larger size of CERN's projects, teams, and ambitions. The CERN SCADA is also not open source. The two approaches make an interesting comparison, since there is inevitably some competition, or at least friendly rivalry, between institutes around the world.</p> <p>The architecture consists of several layers:</p> <ul> <li>A set of physical devices (lasers, magnets, mirrors, rotating pigeons, and magic hats), aka the &quot;front ends&quot;. These run some embedded stack or Linux, and talk over an array of weird and wonderful interfaces such as serial lines.</li> </ul> <ul> <li>A set of &quot;device services&quot; that manage a small group of devices, with custom drivers for each type of device. These device servers expose the devices to the world as addressable objects with properties and some methods. This is the CORBA view of the world as objects. It's not entirely sane, but not totally insane either.</li> </ul> <ul> <li>A name service, which holds a registry of devices and their network addresses (rather, that of the device server which talks to them).</li> </ul> <ul> <li>A set of interactive or batch applications that talk to the device servers using a set of patterns: asynchronous pub-sub, in which devices publish their status; asynchronous request-reply, in which applications query or set device properties, and synchronous request-reply, which is the same but blocking.</li> </ul> <p>There are two API layers that hide the whole messaging stack from normal developers: one for those writing device servers, and one for those writing applications. In both projects the goal is to replace CORBA without modifying the APIs too heavily. CERN has rather more freedom to break the old APIs since the LHC is currently in shutdown, so it's okay to write new applications.</p> <h2><span>Other Thoughts</span></h2> <p>What are the biggest risks and constraints in these projects? Obviously, as in any SCADA, things can't break in ways that damage the whole system. Individual devices will, sometimes, fail. People will write buggy code. But the messaging layer has to be entirely invisible.</p> <p>This means, mainly, no brokers. While CERN, at least, has a lot of brokers (such as ActiveMQ and RabbitMQ), they don't use these in the LHC control middleware, but for other projects. Each project team makes its own choices, and some people just really like STOMP and JMS, for example.</p> <p>Throughput and latency are not yet problems, since in both projects the ambition is to replace a well-known technology with a conceptually similar one. ZeroMQ does have higher latency for the synchronous request-reply case but this doesn't matter (it never does; in any real low-latency design you will always work asynchronously).</p> <p>However as ESRF and CERN gain more experience and confidence with ZeroMQ, I would expect them to move to more interesting use cases. Multicast is an obvious one since there are thousands of devices talking to hundreds of applications. But there are a few other areas where the ZeroMQ community could help a lot over time:</p> <ul> <li>Building a reusable name server (this would be so useful I plan to make one anyhow, so that &quot;bind&quot; automatically registers a new service, and &quot;connect&quot; automatically looks it up).</li> </ul> <ul> <li>Standardizing on protocols based on <a href="http://rfc.zeromq.org/spec:23">ZMTP</a> and <a href="http://rfc.zeromq.org/spec:20">ZRE</a> to talk to devices so that the device server layer could be removed.</li> </ul> <ul> <li>Helping ESRF and CERN with the process of building community around their open source layers. At CERN I was fortunate to be able <a href="https://vimeo.com/69666055">to present our community-building process</a> to a hundred or so developers. At ESRF I presented much the same arguments to a packed room of thirty or forty developers.</li> </ul> <h2><span>Conclusions</span></h2> <p>It's nice to see such significant organizations as ESRF and CERN choosing ZeroMQ for their most important control systems. I'd expected a little more competition from other products but there's nothing out there with the same mix of scale (the sheer number of projects in and around ZeroMQ is impressive), maturity, and appeal to developers.</p> <p>With a little patience and attention, we could see ZeroMQ become the technology of choice not just in synchrotrons and accelerators but also factories and airports and more, and ZeroMQ's protocol &#8212; ZMTP &#8212; could become the &quot;Protocol of Things&quot; for the Internet of Things. Which would be fitting, since the Web was invented at CERN.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:45</guid>
				<title>Securing ZeroMQ: Circus Time</title>
				<link>http://hintjens.wikidot.com/blog:45</link>
				<description>

&lt;p&gt;Thanks to the quiet but persistent work of Martin Hurton, &lt;a href=&quot;https://github.com/zeromq/libzmq&quot;&gt;the master branch of libzmq&lt;/a&gt;, the ZeroMQ core library, now &amp;quot;does security&amp;quot;. In this last article in the mini-series, &amp;quot;Securing ZeroMQ&amp;quot;, I&#039;ll explain what we built, and why, and how this can work for your ZeroMQ applications.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 04 Jul 2013 16:59:01 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Thanks to the quiet but persistent work of Martin Hurton, <a href="https://github.com/zeromq/libzmq">the master branch of libzmq</a>, the ZeroMQ core library, now &quot;does security&quot;. In this last article in the mini-series, &quot;Securing ZeroMQ&quot;, I'll explain what we built, and why, and how this can work for your ZeroMQ applications.</p> <h2><span>Preamble</span></h2> <p>Let me start by stating for the record that I'm not a security expert. I've got many&#8230; <em>talents</em>, such as knowing immediately if someone has sipped from my glass of beer, or making too many friends in too many places. But a deep and confident knowledge of how to stop the NSA reading my most private communications isn't one of them. However, the goal of this exercise is indeed to give us secure communications using ZeroMQ.</p> <p>What is &quot;security&quot;? It's not one thing but a lot of answers to a lot of problems. At the core if A says something confidential to B, then A wants to know that C can't read it, can't modify it, can't pretend to be B, and can't imitate A either. But it goes further than this. Sometimes C will simply steal B's laptop, or kidnap B and torture him to give up his secret passwords.</p> <p>If you study this long enough, you realize no-one is really a security expert. There are cryptographers and mathematicians, protocol designers and malware specialists, operating system security experts, code breakers and forensic cryptographers and on and on. I don't think any single person or team can build &quot;security&quot; or can even really know all the angles. What use is the best security library in the world if the application allows trivial SQL injections? Or if the operating system has known vulnerabilities? Or if the system admin is corrupt?</p> <p>So this brings us back to something I repeat often in my writing and talks: it takes a big, diverse community to solve the hardest problems decently and cheaply. Luckily ZeroMQ is just that, which means given the &quot;what&quot; and the &quot;who&quot;, I can segue into the &quot;how&quot;.</p> <h2><span>How to solve a Very Difficult Problem</span></h2> <p>To solve a VDP, one starts by building a Minimal Plausible Solution, or MPS, and throwing this into the circus where the crowd can gather to watch it being torn apart by wild animals and religious fanatics. The crowd then realizes they can do better, so they make improvements and changes to the MPS and in turn throw these better versions into the ring. Over time the sport develops into a wild and furious game where the crowd split into factions each cheering different variations, and the noise attracts yet more wild animals and fanatics.</p> <p>It's not quite that simple, but more or less, if you can throw a MPS into the ring and if people can improve this freely, you have a decent chance of seeing really good solutions emerge over time.</p> <p>What are the characteristics of a good MPS? First, it must not take itself too seriously. You're designing Steak Tartar, remember. It has to be provocative and cheerfully cheap and simple. You're aiming for <em>plausibility</em>, not <em>certainty</em>.</p> <p>Second, it has to at least work, so it can walk under its own power into the center of the ring, ready to be torn apart. We want the spectacle, the bloodshed, the drama, for it's this that pushes others to get involved. No crowd ever rioted after being shown a 50-slide PowerPoint.</p> <p>Third, it has to be remixable in all directions. In the old days, when we ran punched card FORTRAN-77 on UNIVAC mainframes, we built security systems via committees of gray bearded elders who signed contracts defining who was allowed to make improvements to their Codes. These days we push everything under the (L)GPL and the use GitHub fork+pull request model. Old men are still welcome but only if they cut off their beards.</p> <p>One of my talents is, I think, designing great MPSs and understanding how the circus works.</p> <p>So this is what we've done for security for ZeroMQ. As you ask, &quot;why didn't you implement SSL or TLS?&quot;, that makes you one of the wild animals. Enjoy the <em>Steak haché tartare</em>, it was meant for you.</p> <h2><span>Collecting the Problems</span></h2> <p>Diving down into the real grist of a minimal plausible solution, we need to collect some valid problems. It's no use producing an MPS for the wrong problems, that does nothing except waste everyone's time.</p> <p>So what are the problems we need to solve first? You'd think it was something like &quot;how do we implement a TLS handshake?&quot; or some-such. But it turns out to be more meta than that. I started my research by looking at various security models, and making some quite elegant prototypes, but all I really learned was that choosing any particular model would be a mistake.</p> <p>This is the first problem to solve: our own guaranteed incompetency when it comes to security. Even if we could build a perfect security model today (which I really doubt), it would become broken over time. It is not smart to build an expiration date into your software, especially if you are trying to make general purpose, long-lasting infrastructure, which is our goal with ZeroMQ.</p> <p>There is, luckily, a known way to avoid having to choose a single security model, exemplified by <a href="http://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer">SASL</a>, an Internet security standard that's been used in quite a few protocols now. What SASL does, which is neat, is to delegate all security to a &quot;mechanism&quot; that client and server can implement independently of the rest of the protocol.</p> <p>I find SASL overly complex, so would not implement it as-such unless someone was paying me to be inefficient. However it's quite doable to get the same effect with a simpler design. We stick a &quot;mechanism name&quot; into our protocol, and then depending on the mechanism the client and server propose, we call some plug-in library to handle the actual handshake.</p> <p>The second problem is how to codify this so that we can get multiple independent implementations. It would be a big mistake to start by writing code (except as throw-away experiments). We need some formality that different stacks can aim at. Thus, standardization, and more specifically, in the <a href="http://rfc.zeromq.org/spec:23/ZMTP">ZeroMQ Message Transport Protocol</a> (ZMTP) we use to tie our networks together.</p> <p>Next, we need to prove our design by making a few different security mechanisms. It would be poor taste to force everyone into using full encryption, whether they need it or not. Some protocols then offer an on/off choice (e.g. insecure or secure HTTP). But it's smarter, I believe, to offer N choices, which can cover a spectrum of options. It fits with notion of extensible security and it also seems to fit what people really want, which is a sliding scale of trade-offs (usually performance and simplicity versus security).</p> <p>So, let's recap our first set of problems:</p> <ul> <li>Making an extensible security model.</li> <li>Writing this up as a proper protocol specification.</li> <li>Creating a first set of security mechanisms.</li> </ul> <p>We've been evolving ZMTP for some years from a <a href="http://rfc.zeromq.org/spec:1/SPB">minimal adolescent framing protocol</a> to a more <a href="http://rfc.zeromq.org/spec:15/ZMTP">adult industrial-strength protocol</a>. For example, adding a version header made it possible for newer versions of libzmq to talk safely to older ones, something that was impossible before.</p> <p>ZMTP 3.0 basically breaks down into four layers or phases:</p> <div class="code"> <pre><code>+-------------------------------+ | Version detection | +-------------------------------+ | Security handshake | +-------------------------------+ | Metadata exchange | +-------------------------------+ | Messages and commands | +-------------------------------+</code></pre></div> <p>The two peers exchange signatures and agree on a version; they then exchange credentials and agree on their security; they then exchange meta-data; and they then exchange commands and messages. The security handshake happens as early as possible to avoid leaking any information (the metadata) about peers.</p> <p>I'm not going to explain ZMTP in much detail since there is <a href="http://rfc.zeromq.org/spec:23/ZMTP">a detailed RFC</a>. But I can explain some of the design decisions. The mechanism is a single string. The two peers have to agree on this, or they can't work together. This is one big deviation from SASL, which allows peers to negotiate security dynamically. That could work in ZeroMQ but would force us to make the message API more complex (to indicate the level of security of the sender). We can't prove we need SASL's extra flexibility. So we allow just a single security mechanism.</p> <p>ZMTP then specifies three default security mechanisms, NULL, <a href="http://rfc.zeromq.org/spec:24/ZMTP-PLAIN">PLAIN</a>, and <a href="http://rfc.zeromq.org/spec:25/ZMTP-CURVE">CURVE</a>. The last two are specified by their own RFCs. They all use a somewhat similar handshake. The libzmq library implements the three mechanisms as separate classes.</p> <p>So extensibility is now simple: create a new RFC that documents a new mechanism, and add the necessary class to libzmq. It's probably a week or two of work to add a new security mechanism like DTLS.</p> <p>I'll briefly explain the three mechanisms. NULL means the client doesn't provide any credentials. We can check things like the IP address. PLAIN means the client provides a name and password, without encryption. It's meant to stop us doing stupid things like sending test data to production servers. Finally, CURVE implements an elliptic curve handshake called CurveZMQ, which is based on CurveCP. I'll explain this next.</p> <h2><span>Elliptic Curve Security, CurveCP, and CurveZMQ</span></h2> <p>CurveZMQ is a MPS for &quot;full security&quot; that was a lot more fun to make, and plausibly much more valuable, than an older asymmetric encryption model. I'm not a security expert, but elliptic curve cryptography, or ECC, <a href="http://www.linuxjournal.com/content/elliptic-curve-cryptography">works with shorter keys</a> and uses less CPU than conventional cryptography.</p> <p>However that's almost incidental. The real reason I chose to make CurveZMQ is because of something called <a href="http://curvecp.org">CurveCP</a>, a protocol and stack designed by mathematician and cryptographer Daniel J. Bernstein, author of the NaCl library. CurveCP was announced at the 27th Chaos Communication Congress on 28 December 2010 and CurveCP implementations are still considered experimental. I'm not going to claim CurveCP has any magical properties, is superior, or even works as-such. Indeed, the CurveCP protocol and software really could not work with ZeroMQ in any easy way, since it's designed to work over UDP.</p> <p>Nonetheless, CurveCP starts with a handshake between client and server, and this handshake turns out, after we chop and cook it in various ways, to work very well both over TCP and over ZeroMQ DEALER-ROUTER, and to fit into our SASL-lite security model. There's <a href="http://rfc.zeromq.org/spec:26/CURVEZMQ">a detailed RFC for CurveZMQ</a> which explains the precise chopping and cooking I had to do.</p> <p>CurveZMQ is essentially the CurveCP handshake, trimmed and cleaned-up to work over any bidirectional message transport, and documented as an RFC. I'm not yet sure how good or bad this is, but recall that we can't afford to take any particular mechanism too seriously. This is a minimal plausible solution for encryption, no more or less.</p> <p>What immediately caught my attention was DJB's stated goal of making his APIs simple. The NaCl API is beautifully simple. I've worked with OpenSSL and it uses the industry standard approach of &quot;expose every possible choice upfront with zero hints as to what is really vital, and what you will never ever use&quot;.</p> <p>Whereas NaCl hides everything it can, on the theory that offering choices to people like me about what what key sizes or hashing algorithms to use is just asking for trouble. And I totally agree. NaCl is really like ZeroMQ, it hides choices we usually only get wrong.</p> <p>Love at first sight! Whether or not the thing actually works, it was fun to learn and use and that's a powerful indicator. NaCl is in fact wrapped up as <a href="https://github.com/jedisct1/libsodium">libsodium</a>, which is the library we use.</p> <p>So I wrote up CurveZMQ as a proper RFC and made <a href="https://github.com/zeromq/libcurve">a reference implementation</a>. This library serves a double purpose. It acts as a guide to people implementing CurveZMQ and it can also be used by applications to do CurveZMQ encoding above ZeroMQ, to get end-to-end encryption. This is a little complex, and I'll make a real example app sometime to demonstrate it.</p> <h3><span>Helicopter View of CurveZMQ</span></h3> <p>To start a secure connection the client needs the server long term key. It then generates a short term key pair and sends a HELLO command to the server that contains its short term public key. The HELLO command is worthless to an attacker; it doesn't identify the client.</p> <p>The server, when it gets a HELLO, generates its own short term key pair (one connection uses four keys in total), and encodes this new private key in a &quot;cookie&quot;, which it sends back to the client as a WELCOME command. It also sends its short term public key, encrypted so only the client can read it. It then discards this short term key pair.</p> <p>At this stage, the server hasn't stored any state for the client. It's generated a keypair, sent that back to the client in a way only the client can read, and thrown it away.</p> <p>The client comes back with an INITIATE command that provides the server with its cookie back, and the client long term public key, encrypted so only the server can read it. As far as the client is concerned, the server is now authenticated, so it can also send back metadata in the command.</p> <p>The server reads the INITIATE and can now authenticate the client long term key. It also unpacks the cookie and gets its short term key pair for the connection. As far as the server is now concerned, the client is now authenticated, so the server can send its metadata safely. Both sides can then send messages and commands.</p> <p>This handshake provides a number of protections but mainly, <em>perfect forward security</em> (you cannot crack data encrypted using the short term keys even if you record it, and then later get access to the long term keys) and <em>protection of client identity</em> (the client long term key is not sent in clear-text).</p> <h3><span>Security Goals for CurveZMQ</span></h3> <p>Despite treating CurveZMQ as a disposable MPS, I want it to be solid against at least these attacks (this list is based on the CurveCP documentation):</p> <ul> <li><em>Eavesdropping,</em> in which an attacker sitting between the client and server monitors the data. We send all in boxes that only the authentic recipient, knowing the necessary secret key, can open.</li> </ul> <ul> <li><em>Fraudulent data,</em> in which an attacker creates packets that claim to come from the server or client. Only the authentic sender, knowing the necessary secret key, can create a valid box, and thus a valid packet.</li> </ul> <ul> <li><em>Altering data,</em> in which an attacker sitting between client and server manipulates packets in specific ways. If a packet is modified in any way, the box it contains will not open, so the recipient knows there has been an attack and discards the packet.</li> </ul> <ul> <li><em>Replaying data,</em> in which an attacker captures packets and re-sends them later to imitate a valid peer. We encrypt every box with a unique nonce. An attacker cannot replay any packet except a Hello packet, which has no impact on the server or client. Any other replayed packet will be discarded by its recipient.</li> </ul> <ul> <li><em>Amplification attacks,</em> in which an attacker makes many small unauthenticated requests but uses a fake origin address so large responses are sent to that innocent party, overwhelming it. Only a Hello packets are unauthenticated, and they are padded to be larger than Cookie packets.</li> </ul> <ul> <li><em>Man-in-the-middle attacks,</em> in which an attacker sitting between client and server substitutes its own keys so it can play &quot;server&quot; to the client and play &quot;client&quot; to the server, and thus be able to open all boxes. Since long-term keys are known beforehand, an attacker cannot successfully imitate a server, nor a client if the server does client authentication.</li> </ul> <ul> <li><em>Key theft attacks,</em> in which an attacker records encrypted data, then seizes the secret keys at some later stage, perhaps by physically attacking the client or server computer. Client and server use connection keys that they throw away when they close the connection.</li> </ul> <ul> <li><em>Identifying the client,</em> in which an attacker traces the identity of a client by extracting its public long-term key from packets. The client sends this only in an Initiate packet, protected by the connection keys.</li> </ul> <ul> <li><em>Denial-of-Service attacks,</em> in which an attacker forces the server to perform expensive operations before authentication, thus exhausting the server. CurveCP uses high-speed high-security elliptic-curve cryptography so that a typical CPU can perform public-key operations faster than a typical Internet connection can ask for those operations. The server does not allocate memory until a client sends the Initiate packet.</li> </ul> <h2><span>Client Authentication</span></h2> <p>When we get a new connection into a server, we may have to check whether the client is allowed to connect or not. It's one of those problems that gets complex and messy quite quickly. Do we support password files, key files, databases, LDAP, PAM, GSSAPI, etc.?</p> <p>As usual my favorite way to solve complex problems is to cheat and make this &quot;someone else's problem&quot;. For authentication, what I wanted was a way to <em>not implement</em> any of the above list in the libzmq library, and still make it simple to support any of the above.</p> <p>The answer in this case is to use ZeroMQ itself. The library, getting a new connection, sends a message requesting a yes/no decision, and someone gets the message, does the work, and sends a reply:</p> <div class="code"> <pre><code>+----------+ | | | Client | | | +----------+ | | TCP connection V +----------+ | | | Server | | | +----------+ | REQ | +----------+ inproc:// | REP | +----------+ | | | Handler | | | +----------+</code></pre></div> <p>We can use the REQ-REP pattern over <span style="white-space: pre-wrap;">inproc://</span>. If the process is built without any handler, the server won't authenticate clients (will allow them all). A handler can also proxy requests to out-of-process handlers, over local networking or <span style="white-space: pre-wrap;">ipc://</span>.</p> <p>I wrote this up as an RFC, called <a href="http://rfc.zeromq.org/spec:27/ZAP">the ZeroMQ Authentication Protocol</a>, or ZAP. Here's an example of a ZAP authentication request sent by a server to a handler, for a client using the PLAIN mechanism:</p> <div class="code"> <pre><code>+-+ | | Empty delimiter frame +-+---+ | 1.0 | Version number +-----++ | 0001 | Request ID, for example &quot;0001&quot; +------+ | test | Domain, empty in this case +------+-------+ | 192.168.55.1 | Address +-------+------+ | PLAIN | Mechanism +-------+ | admin | Username +-------++ | secret | Password +--------+</code></pre></div> <p>This shows an example reply from the handler to the server:</p> <div class="code"> <pre><code>+-+ | | Empty delimiter frame +-+---+ | 1.0 | Version number +-----++ | 0001 | Request ID echoed from request +-----++ | 200 | Status code +----++ | OK | Status text +----++ | joe | User id +-+---+ | | Metadata, empty +-+</code></pre></div> <p>It's a neat design because it works entirely out-of-band. That is, authentication doesn't affect message flow, can take as long as it has to, and can be handled by components that are fully independent of the application.</p> <h2><span>The ZeroMQ Security API</span></h2> <p>The security API is a set of new options that you apply to client or server sockets.</p> <p>Here's how we configure a server socket for PLAIN security:</p> <div class="code"> <pre><code>as_server = 1; zmq_setsockopt (server, ZMQ_PLAIN_SERVER, &amp;as_server, sizeof (int));</code></pre></div> <p>And here's how we configure a client socket, which needs to know a username and password to send to the server:</p> <div class="code"> <pre><code>strcpy (username, &quot;admin&quot;); strcpy (password, &quot;password&quot;); zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username)); zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password));</code></pre></div> <p>Here's how we configure a server socket for CURVE security:</p> <div class="code"> <pre><code>// Test keys from the zmq_curve man page char server_secret [] = &quot;JTKVSB%%)wK0E.X)V&gt;+}o?pNmC{O&amp;4W4b!Ni{Lh6&quot;; as_server = 1; zmq_setsockopt (server, ZMQ_CURVE_SERVER, &amp;as_server, sizeof (int)); zmq_setsockopt (server, ZMQ_CURVE_SECRETKEY, server_secret, 40);</code></pre></div> <p>And here's how we configure a client socket, which needs to know three keys:</p> <div class="code"> <pre><code>// Test keys from the zmq_curve man page char server_public [] = &quot;rq:rM&gt;}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7&quot;; char client_public [] = &quot;Yne@$w-vo&lt;fVvi]a&lt;NY6T1ed:M$fCG*[IaLV{hID&quot;; char client_secret [] = &quot;D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs&quot;; zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40); zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40); zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40);</code></pre></div> <p>The application has to handle key exchange. For now the simplest model is that clients are given the server public key, and servers do not authenticate clients.</p> <h2><span>The Z85 Encoding Standard</span></h2> <p>The nice thing about standards is that you have so much choice. Wikipedia lists more than a dozen Base64 variations of dubious interoperability.</p> <p>Why am I talking about Base64? Because exchanging binary keys is a royal pain. Almost as soon as we tried using CURVE security we hit the problem of how to represent keys in source code. For sure, you can encode binary as escape sequences but that's not portable between languages and doesn't work in configuration files, on the command line, or in emails.</p> <p>Base64 is the common &quot;standard&quot; but it has several things about it that are nasty. First, there is no single standard so there's no real guarantee that Base64 implementations will work together. Second, it is a clumsy fit for binary data, and this is one reason there are so many variations. Base64 encodes 3 bytes of binary data as 4 characters. Yet most chunks of binary data are multiples of 4 or 8 bytes. That &quot;divide by 3&quot; aspect makes Base64 implementations more complex and fragile than such a simple problem deserves.</p> <p>So I took an existing little-used encoding (Ascii85) and fixed it to make it safe to use in strings (so, also in XML, in JSON, on the command line, etc.) The result is <a href="http://rfc.zeromq.org/spec:32/Z85">Z85</a>, which is &quot;more compact than Base16, more reliable than Base64, and more usable than Ascii85&quot;.</p> <p>I like Z85, because <a href="https://raw.github.com/zeromq/libzmq/master/tools/z85_codec.h">the code turned out to be simple and clean</a>. That's always a good sign. The codec I wrote uses a precomputed table to rapidly convert from Base85 (Z85) to Base256 (binary).</p> <p>Some people of course didn't like the introduction of Yet Another RFC, and they're right in some respects. I don't think it matters too much: I enjoyed making this little package; if it becomes a problem to others, someone will make a Base 64 encoding for the libzmq API.</p> <p>The trick is when you do a setsockopt, if the key length is 32, it assumes binary. If the length is 40, it assumes Z85. If the key length is 44 (I think&#8230; or 43 perhaps?) you could assume Base 64.</p> <h2><span>Current Status</span></h2> <p>We got the security test cases running on June 21/22 at our ZeroMQ Developers' Meeting in Brussels, thanks to Ian Barber and Martin Hurton (who did the bulk of the work in libzmq). It's all on libzmq master today, and supported in the CZMQ binding. Other bindings will start to implement the security API options soon.</p> <p>This all works, which is somewhat shocking.</p> <p>It's also remarkably simple, which is also a pleasant surprise. We have, for applications:</p> <ul> <li>Three new options for PLAIN security.</li> <li>Five new options for CURVE security.</li> <li>One inproc:// plug-in endpoint for authentication handlers.</li> <li>One tool that generates new keypairs (in tools/curve_keygen).</li> </ul> <p>And for those who want to get their hands dirty:</p> <ul> <li>Extensible classes in libzmq so anyone can try their hand at new mechanisms.</li> <li>A whole bunch of new <a href="http://rfc.zeromq.org">RFCs</a> along with <a href="https://github.com/zeromq/rfc">reference implementations</a>.</li> </ul> <h2><span>Conclusions</span></h2> <p>Of course no story is over until the main characters have been slaughtered in an orgy of bloodletting that leaves the audience shocked and traumatized and asking &quot;why?&quot; I'm sure CurveZMQ and ZAP and Z85 will get their Red Wedding in time. When it happens, I'd enjoy wielding the knife but it really doesn't matter as long as we make space for further interesting characters over time.</p> <p>I'll be using the new security mechanisms in FileMQ, Zyre, and some other applications. There are a few other things still to fix in libzmq before this is ready for Internet use, and perhaps we'll print this as a new major version. I think it deserves it. But that's another story, for another day.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:42</guid>
				<title>A Web Server in 30 Lines of C</title>
				<link>http://hintjens.wikidot.com/blog:42</link>
				<description>

&lt;p&gt;There are developers who never built distributed systems. Then there are developers who have done this before, using a messaging system. Then there are those who&#039;ve done it the hard way, using BSD sockets. Privately, I call these the Good, the Bad, and the Ugly, because of how they respond when they meet ZeroMQ and read the Guide. Today, &amp;quot;Getting Started with ZeroMQ for Uglies&amp;quot;. With a &amp;quot;Hello, World&amp;quot; web server in —40— 30 lines of C, just for fun.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 29 Apr 2013 09:57:10 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>There are developers who never built distributed systems. Then there are developers who have done this before, using a messaging system. Then there are those who've done it the hard way, using BSD sockets. Privately, I call these the Good, the Bad, and the Ugly, because of how they respond when they meet ZeroMQ and read the Guide. Today, &quot;Getting Started with ZeroMQ for Uglies&quot;. With a &quot;Hello, World&quot; web server in —40— 30 lines of C, just for fun.</p> <h2><span>The Good, the Bad, and the Ugly</span></h2> <p>First, a confession: I'm an Ugly, writing my first distributed fabric in 1990. This was for a pan-European tour operator app, running on Digital ACMS, and it ran for 20 years. It was quite a shock to see formal messaging systems when we started building AMQP for JPMorganChase around 2004. I've come to appreciate the abstractions but it took a long time.</p> <p>The Good, when they see ZeroMQ, don't come with preconceptions. They open a magic box, learn the different tools, and for the most part, experience the kind of euphoric empowerment we dream of when we make software for other people to use. The Good are the people I cherish the most, because their lack of previous experience keeps them open to doing the most exciting, aka crazy, things with ZeroMQ. They also often come from a generation that's used to GitHub, which enjoys making pull requests, and so on.</p> <p>The Bad, when they see ZeroMQ, immediately try to fit it into their view of How Things Work. I've called this the &quot;Fire vs. Electricity&quot; paradox. When you're used to Fire, and you enjoy your grilled mammoth burger, it's kind of freaky to hear someone explaining electricity. The more experience you have with Fire, the more you will dislike this new form of energy. When someone explains, &quot;Sure, you can make a grill, but you can also power your smartphone,&quot; the inclination is to hit the speaker over the head with the chewed-up remnants of a mammoth rib bone. The Bad tend to come to the zeromq-dev mailing list with long and unanswerable questions of the form, &quot;How do I use ZeroMQ to do such-and-such?&quot; which is like asking, &quot;how do I use this thing you call 'electricity' to set fire to the plains so that the mammoth will run over the cliff?&quot;</p> <p>Finally, we have the Ugly. We uglies are experienced technical developers, wise enough to not trust technology, especially technology that is boastful and arrogant enough to claim some kind of uniqueness. We uglies know that most technology is bullshit, and the louder the marketing, the worse it is. We make a lot of stuff ourselves because we like things to work for 20 years. When we come to ZeroMQ, we start trying to fit the Guide to our problems, and soon we give up in a mix of frustration and anger.</p> <p>Now I'm not calling Tavis Rudd &quot;ugly&quot;, and indeed he looks quite handsome in his <a href="https://twitter.com/tavisrudd">Twitter profile pic</a>, but as he says, &quot;<em>finding the ZeroMQ guide a very frustrating read. Great software, but the guide is too chatty, too boastful and poorly structured. True root of my frustration w the zeromq guide was wanting to use req/rep for something I'm much better off doing with plain bsd sockets</em>&quot;.</p> <p>A good designer always takes the blame. As ZeroMQ gets more popular, we get a bigger spread of reactions to the learning curve. Early users were a subset of the Bad (let's call them the Evil), who had already figured out why they wanted decentralized messaging. For them, ZeroMQ was a godsend, and they would have read the source code to figure out how to use it. The Guide was therefore aimed squarely at the other early users, the Good, who were new to messaging and wanted a full story to buy into. Good and Evil, the ingredients of every great creation myth.</p> <h2><span>ZeroMQ Is Just Like BSD Sockets, But Better</span></h2> <p>The other essential ingredients of a creation myth are lies and deception. ZeroMQ is nothing at all like BSD sockets despite very insistent attempts from its early designers to make that. Yes, the API is vaguely socket-like. APIs are not the same as semantics. ZeroMQ patterns are weird and wonderful and delicate but they are not, and I'll repeat this, even marginally close to the BSD &quot;stream of bytes from sender to recipient&quot; pattern.</p> <p>It's worse than that. The closest match in ZeroMQ is the PAIR socket, which is kind of broken in <tt>libzmq</tt>, and which we use only for inter-thread pipes. So innocent Uglies like Tavis start with request-reply sockets, and soon discover that not only is ZeroMQ not like BSD sockets &quot;on steroids&quot; but the very simplest ZeroMQ patterns are useless for them. Request-reply isn't just contrived and weird, it's <em>also</em> broken in interesting ways and is really just a teaching tool for people to get into the <em>real</em> ZeroMQ socket patterns: publish-subscribe, push-pull, and router-dealer.</p> <p>Happily, sometime in 2012, one of the random passing geniuses who contributes to ZeroMQ came up with a patch that gave us raw STREAM sockets. It's about as sane as adding a lighter to your smartphone in an age where most people are just switching from coal to gas. The lighter is surprisingly useful when interfacing with primitive fire-based systems. It makes zero sense in an electricity-based world, but software is more like something from a steampunk comic, a mix of technologies of all ages.</p> <p>When we explain ZeroMQ to the Good, we start at the beginning with the request-reply pattern and move through hundreds of pages to the real gold. I can really imagine how frustrating it must be to come with decades of experience of networking and have to wade through hundreds of pages of explanation to come to the right answer.</p> <p>Of course, if everyone asked the right questions up-front, life would be simpler.</p> <p>The question Tavis didn't really ask was (afaics), &quot;how do I replace plain BSD sockets with ZeroMQ, gradually moving to more interesting use-cases?&quot;</p> <p>Which I'll try to answer, thanks to <a href="https://github.com/hshardeesi">hshardeesi</a> and his RAW patch. Let's assume we're talking about TCP, because UDP is special in its own cute ways.</p> <h2><span>Moving from BSD Sockets to ZeroMQ Sockets</span></h2> <h3><span>Step One: STREAM sockets</span></h3> <p>First, we'll get a ZeroMQ socket talking to a classic TCP socket. Then we'll morph that into a ZeroMQ-to-ZeroMQ connection. Let's break this down into steps:</p> <ul> <li>Forget REQ, REP, and PAIR sockets, We're going to use a ZMQ_STREAM socket. I'll show you code you can cut/paste in a second.</li> </ul> <ul> <li>The stream socket acts as a server, so bind it to a <tt>tcp://</tt> endpoint that you expect clients to connect to.</li> </ul> <ul> <li>You can talk to clients <em>after</em> they talk to you. Just like a TCP server socket. The RAW option doesn't let you talk to a TCP peer until it's talked to you.</li> </ul> <ul> <li>You read messages from the socket one after the other, either using blocking <tt>zmq_recv</tt> calls, or using <tt>zmq_poll</tt>. Each message has two frames. The first frame is the handle of the client (ZeroMQ calls this the &quot;identity&quot;). The second frame is the received data, which is 1 or more bytes.</li> </ul> <ul> <li>To send data back to a specific client, you first send the handle, and then the data, as two frames. If you want to close a client connection, send the handle and then an empty frame.</li> </ul> <p>That's it. The stream socket takes care of all the multiplexing, error handling, polling, and so on, and does this in a background I/O thread so it's fast.</p> <p>What kind of havoc can we create using a stream socket? How about a web server? That's always fun. OK, here's a 30-line HTTP server in C. This little animal doesn't do much real work. It reads requests, logs them, chucks them out, and answers &quot;Hello, World!&quot;:</p> <div class="code"> <p><span style="color:#BC7A00"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Minimal HTTP server in 0MQ<br /> #include &quot;czmq.h&quot;</span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_t <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>stream <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_STREAM);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zsocket_bind (stream, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:8080&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (rc <span style="color:#666666">!=</span> <span style="color:#666666">-</span><span style="color:#666666">1</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (<span style="color:#008000">true</span>) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Get HTTP request</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_t <span style="color:#666666">*</span>handle <span style="color:#666666">=</span> zframe_recv (stream);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (<span style="color:#666666">!</span>handle)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Ctrl-C interrupt</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>request <span style="color:#666666">=</span> zstr_recv (stream);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>puts (request);<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Professional Logging(TM)</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>free (request);<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We throw this away</em></span></p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send Hello World response</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_send (<span style="color:#666666">&amp;</span>handle, stream, ZFRAME_MORE <span style="color:#666666">+</span> ZFRAME_REUSE);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zstr_send (stream,<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#BA2121">&quot;HTTP/1.0&#160;200 OK</span><span style="color:#BB6622"><strong>\r\n</strong></span><span style="color:#BA2121">&quot;</span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#BA2121">&quot;Content-Type: text/plain</span><span style="color:#BB6622"><strong>\r\n</strong></span><span style="color:#BA2121">&quot;</span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#BA2121">&quot;</span><span style="color:#BB6622"><strong>\r\n</strong></span><span style="color:#BA2121">&quot;</span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#BA2121">&quot;Hello, World!&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Close connection to browser</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_send (<span style="color:#666666">&amp;</span>handle, stream, ZFRAME_MORE);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zmq_send (stream, <span style="color:#008000">NULL</span>, <span style="color:#666666">0</span>, <span style="color:#666666">0</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>zhttpd.c: HTTP Server</em> <p><a href="https://gist.github.com/hintjens/5480625">Get the code.</a></p> <p>To make this into a real server we'd have to add at least a few things:</p> <ul> <li>Read a full HTTP request header, which means keep reading and accumulating data until we find a blank line (two carriage-returns) in the data.</li> </ul> <ul> <li>Parse the HTTP request to see if the client has asked us for something we can handle, e.g. to GET a resource.</li> </ul> <ul> <li>Map that resource name into a real filename (if that's what we're trying to do).</li> </ul> <ul> <li>Open the file, and send its contents to the client.</li> </ul> <p>But that's classic RFC2616 stuff and not relevant to ZeroMQ, so not really worth talking about more. 2616ing used to be a full-time hobby but honestly, ZeroMQ is way more fun.</p> <h3><span>Step Two: ROUTER to DEALER</span></h3> <p>So, you've now seen how ZeroMQ can talk to BSD sockets. It's not perfect: for one thing, we can't write clients like this. That sucks. If anyone wants to fix this, perhaps allow outgoing connections on a STREAM socket, resulting in a null message back to the caller, with an identity and zero body.</p> <p>Anyhow, what's the next step? Let's replace the BSD TCP socket with a DEALER socket. It's not a perfect match but it's close enough to make a good party. If we connect DEALER to exactly one ROUTER, the DEALER just reads and writes like a TCP socket, with some small but oh-so-valuable differences:</p> <ul> <li>We can write any amount of data <em>as a single message</em> and it will arrive <em>as a single message</em>. This is awesome because using a classic TCP protocol like HTTP means doing a lot of dancing around the pot to figure out when a request or response is finished. Framing, young man, the future is in framing!</li> </ul> <ul> <li>The DEALER socket will connect opportunistically. Again, a small but awesome improvement on the BSD style of networking. Just connect one time, then use the socket for ages. It'll disconnect and reconnect as the network shifts. Perhaps the ROUTER socket will decide it wants to flush connections. No problem! The DEALER will reconnect later.</li> </ul> <p>DEALER does quite a lot more than this. It can connect to many ROUTERs and will distribute requests among them. Load-balancing, for free. It does fair queuing on input, so if you're getting a gigabyte of messages from one ROUTER, and another sends you a 10-byte urgent message, that will sneak in front.</p> <p>Doing a DEALER-to-ROUTER pseudo-HTTP is of course weird, it's just an exercise. We'll call the protocol WTFP, and it looks (nothing at all) like HTTP over ZeroMQ framing:</p> <div class="code"> <p><span style="color:#BC7A00"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Minimal WTFP server in 0MQ<br /> #include &quot;czmq.h&quot;</span></p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span> <span style="color:#666666">*</span><br /> <span style="color:#0000FF">wtfp_server</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_t <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>router <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_STREAM);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zsocket_bind (router, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:8080&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (rc <span style="color:#666666">!=</span> <span style="color:#666666">-</span><span style="color:#666666">1</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (<span style="color:#008000">true</span>) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Get WTFP request</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_t <span style="color:#666666">*</span>handle <span style="color:#666666">=</span> zframe_recv (router);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (<span style="color:#666666">!</span>handle)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Ctrl-C interrupt</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>request <span style="color:#666666">=</span> zstr_recv (router);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>puts (request);<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Professional Logging(TM)</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>free (request);<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We throw this away</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Send Hello World response</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_send (<span style="color:#666666">&amp;</span>handle, router, ZFRAME_MORE);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zstr_send (router, <span style="color:#BA2121">&quot;Hello, World!&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#008000">NULL</span>;<br /> }</p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zthread_new (wtfp_server, <span style="color:#008000">NULL</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_t <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>dealer <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_DEALER);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zsocket_connect (dealer, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>localhost:8080&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>assert (rc <span style="color:#666666">!=</span> <span style="color:#666666">-</span><span style="color:#666666">1</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (dealer, <span style="color:#BA2121">&quot;GET /Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>response <span style="color:#666666">=</span> zstr_recv (dealer);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (response);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>zwtfpd.c: WTFP Server</em> <p><a href="https://gist.github.com/hintjens/5480688">Get the code.</a></p> <h3><span>Satori</span></h3> <p>So now we've seen how ZeroMQ can roughly imitate BSD sockets, talk to them, and then fark them up beyond all recognition. DEALER-ROUTER is what we use in most real large-scale architectures, because it lets us build real bidirectional protocols. But there's also PUSH-PULL and PUB-SUB, which are fun. Not to mention using ZeroMQ for in-process multithreading. When you think of distribution not just as &quot;outer&quot; but also &quot;inner&quot;, you start to see just how ambitious and arrogant this library is.</p> <p>Hope you enjoyed the article. Let me know what you want me to write about next.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:39</guid>
				<title>Securing ZeroMQ: draft ZMTP v3.0 Protocol</title>
				<link>http://hintjens.wikidot.com/blog:39</link>
				<description>

&lt;p&gt;In &lt;a href=&quot;http://hintjens.wikidot.com/blog:36&quot;&gt;the previous article&lt;/a&gt; in this series, &amp;quot;Securing ZeroMQ&amp;quot;, I showed a proof-of-concept for CurveZMQ. Now we&#039;re moving that into the ZeroMQ protocol, ZMTP. It&#039;s not a small change. You can&#039;t just sprinkle security over a protocol like chocolate chips onto pancakes. It means a new protocol, and this gives us a chance to address other problems with ZMTP. The result is &lt;a href=&quot;http://rfc.zeromq.org/spec:23&quot;&gt;ZMTP v3.0&lt;/a&gt;. In this article I&#039;ll explain ZMTP v3.0. If you never read the 1.0 or 2.0 spec, don&#039;t worry, I&#039;ll cover those briefly too.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 14 Apr 2013 11:15:56 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>In <a href="http://hintjens.wikidot.com/blog:36">the previous article</a> in this series, &quot;Securing ZeroMQ&quot;, I showed a proof-of-concept for CurveZMQ. Now we're moving that into the ZeroMQ protocol, ZMTP. It's not a small change. You can't just sprinkle security over a protocol like chocolate chips onto pancakes. It means a new protocol, and this gives us a chance to address other problems with ZMTP. The result is <a href="http://rfc.zeromq.org/spec:23">ZMTP v3.0</a>. In this article I'll explain ZMTP v3.0. If you never read the 1.0 or 2.0 spec, don't worry, I'll cover those briefly too.</p> <table style="margin:0; padding:0"> <tr> <td style="margin:0; padding:0"> <div id="toc"> <div id="toc-action-bar"><a href="javascript:;" >Fold</a><a style="display: none" href="javascript:;" >Unfold</a></div> <div class="title">Table of Contents</div> <div id="toc-list"> <div style="margin-left: 2em;"><a href="#toc0">Real Protocols are Worth It</a></div> <div style="margin-left: 2em;"><a href="#toc1">Goals</a></div> <div style="margin-left: 2em;"><a href="#toc2">Overall Behavior</a></div> <div style="margin-left: 2em;"><a href="#toc3">Version Negotiation</a></div> <div style="margin-left: 2em;"><a href="#toc4">Commands, Messages and Frames</a></div> <div style="margin-left: 2em;"><a href="#toc5">Authentication and Confidentiality</a></div> <div style="margin-left: 2em;"><a href="#toc6">The NULL Security Mechanism</a></div> <div style="margin-left: 2em;"><a href="#toc7">The PLAIN Mechanism</a></div> <div style="margin-left: 2em;"><a href="#toc8">The CURVE Mechanism</a></div> <div style="margin-left: 2em;"><a href="#toc9">Pluggable Authentication</a></div> <div style="margin-left: 2em;"><a href="#toc10">Connection Metadata</a></div> <div style="margin-left: 2em;"><a href="#toc11">Virtual Addressing</a></div> <div style="margin-left: 2em;"><a href="#toc12">Security Considerations</a></div> <div style="margin-left: 2em;"><a href="#toc13">Conclusions</a></div> </div> </div> </td> </tr> </table> <h2><span>Real Protocols are Worth It</span></h2> <p>ZeroMQ used to have a sweet but unrealistic story: &quot;our API looks like plain sockets, and we have practically no protocol&quot;. As it turns out, this was great marketing but not great technical design. The plain BSD socket API doesn't work for messaging (Contexts? Multipart messages? Zero-copy? Events? Threads?), and a non-protocol doesn't provide the number one guarantee users want, which is interoperability (you need version numbers).</p> <p>ZMTP v1.0 was simple: each peer connected and then started blasting messages to each other. This is the protocol that libzmq v2.x speaks. The later release, v3.1 speaks a dialect of this protocol where subscribers send subscriptions upstream to publishers. You can't mix v2.x and v3.1 pub-sub on the same network.</p> <p>We designed and implemented ZMTP v2.0 about a year ago. It added version numbering, and fixed the framing to be more sensible. This is the protocol the current libzmq v3.2 speaks (it will also downgrade to speak to older 2.x peers). It was a minimal change, and didn't address a bunch of other problems in ZMTP.</p> <p>By 2013 it was clear that the number one problem with ZMTP is the lack of security. As I've shown in previous articles, it's not technically so difficult. It just needs to be done. At the same time, since adding security means big changes, we (Martin Hurton and myself) decided to address a few of the other long-standing problems in the protocol. These are mostly just questions the protocol should answer, but didn't.</p> <p>As you read these changes, understand the <a href="http://hintjens.com/blog:9">&quot;Cheap and Nasty&quot;</a> pattern. We connect once, and then exchange millions of messages over hours or days. The message transfer is asynchronous, changes very little over time, and has to be as efficient as possible. But creating a connection is synchronous, changes a lot over time, and efficiency is utterly irrelevant.</p> <p>When you get this, you begin to see how to design what I'd consider a real messaging protocol. It breaks into two parts: a chatty negotiation at the start, and a high-speed asynchronous data stream thereafter. The negotiation needs to define commands with structure, and extensibility in the form of dictionaries (binary, or text, it doesn't really matter). ZMTP v2.0 didn't even start to go into this direction. In fact it broke that pattern by for instance sending meta data (identities and subscriptions) as messages.</p> <h2><span>Goals</span></h2> <p>A good way to understand ZMTP is to start with a plain TCP connection and then see what problems we need to solve in order to get a working message transport:</p> <ul> <li>TCP carries a stream of bytes with no delimiters, but we want to send and receive discrete messages. Thus, ZMTP reads and writes <em>frames</em> consisting of a size and a body.</li> </ul> <ul> <li>We need to carry metadata on each frame (such as, whether the frame is part of a multipart message, or not). ZMTP provides a <em>flags</em> field in each frame for metadata.</li> </ul> <ul> <li>We need to be able to talk to older implementations, so that our framing can evolve without breaking existing implementations. ZMTP defines a <em>greeting</em> that announces the implemented version number, and specifies a method for version negotiation.</li> </ul> <ul> <li>We need security so that peers can be sure of the identity of the peers they talk to, and so that messages cannot be tampered with, nor inspected, by third parties. ZMTP defines a <em>security handshake</em> that allows peers to create a secure connection.</li> </ul> <ul> <li>We need a range of security protocols, from clear text (no security, but fast) to fully authenticated and encrypted (secure, but slow). Further, we need the freedom to add new security protocols over time. ZMTP defines a way for peers to agree on an extensible <em>security mechanism</em>.</li> </ul> <ul> <li>We need a way to carry metadata about the connection, after the security handshake. ZMTP defines a standard set of <em>metadata properties</em> (socket type, identity, etc.) that peers exchange after the security mechanism.</li> </ul> <ul> <li>We want to allow multiple tasks to share a single external unique interface and port, to decrease system administration costs. ZMTP defines a <em>resource</em> metadata property that lets any number of tasks share a single interface and port.</li> </ul> <h2><span>Overall Behavior</span></h2> <p>A ZMTP connection goes through these main stages:</p> <ul> <li>The two peers agree on the version and security mechanism of the connection by sending each other data and either continuing the discussion, or closing the connection.</li> <li>The two peers handshake the security mechanism by exchanging zero or more commands. If the security handshake is successful, the peers continue the discussion, otherwise one or both peers closes the connection.</li> <li>Each peer then sends the other metadata about the connection as a final command. The peers may check the metadata and each peer decides either to continue, or to close the connection.</li> <li>Each peer is then able to send the other messages. Either peer may at any moment close the connection.</li> </ul> <h2><span>Version Negotiation</span></h2> <p>ZMTP v3.0 makes it much clearer how to do version negotiation. Each peer sends part of the greeting, and the higher version number can decide to downgrade to the lower version number. Thus implementations can choose to be backwards compatible (as libzmq is), but do not need to try to be forwards compatible (which is kind of hard). If you're a v3.0 peer and you get a greeting from a v4.0 peer, you just continue. If the 4.0 peer doesn't want to downgrade to your protocol, it'll close the connection.</p> <h2><span>Commands, Messages and Frames</span></h2> <p>Following the greeting, which has a fixed size of 64 octets, all further data is sent as size-specified frames. <em>Command frames</em> are used in the security handshake, and <em>message frames</em> are used to carry clear text application data. Commands always consist of a single frame. Messages consist of one or more frames.</p> <p>A ZMTP connection is either clear text, or encrypted, according to the security mechanism. On a clear text connection, message data is always sent as message frames, using a single consistent format, so that traffic analysis tools don't need to know the specific details of a clear text mechanism. On an encrypted connection, message data is always encoded as commands so that wire analysis is not possible. (You'll never see message frames on a secure connection, period.)</p> <p>The frame has the same format as in v2.0 (like I said, the asynchronous high-volume part of a protocol rarely changes once you get it right). It has a 1 byte flags field, followed by one or eight bytes of size, followed by body data. The only change we made in v3.0 was to add another flag bit to mark command frames.</p> <p>People have proposed various other flag fields in the past, e.g. marking the first and last frame of a message rather than &quot;more&quot;. Or, adding a &quot;label&quot; bit to mark message envelopes separately from message content (this would get rid of the null delimiter frame that request-reply still uses).</p> <p>Right now, ZMTP still doesn't know much about actual socket semantics, but we could start to add this. I'd like, for example, to be more explicit about XSUB/XPUB subscribe and unsubscribe commands, which are now sent as messages with a special first byte. We could also do heartbeating and more. Actually it's not hard to add features. The real cost is not even implementing them, it's ensuring existing applications can migrate safely onto new stacks.</p> <h2><span>Authentication and Confidentiality</span></h2> <p>Now we come to the meat of ZMTP v3.0, which is security. More specifically, do we know who we're talking to, and are our conversations fully private?</p> <p>Making secure protocols is complex, dangerous, and thankless work unless you find a way to cheat and make it all Someone Else's Problem. For ZMTP I borrowed from the IETF's Simple Authentication and Security Layer (SASL), aka <a href="http://tools.ietf.org/html/rfc4422">RFC 4422</a>, and the NaCl <a href="http://curvecp.org">CurveCP security handshake</a>. (I've explained my proposal for creative abuse of CurveCP in previous articles.)</p> <p>If you haven't studied SASL, and you care even a little about security protocols, you should go off and read my latest book, called &quot;SASL Made Simple&quot; (1,350 pages, from iMatix University Press, $95.50 plus S&amp;H). Just kidding&#8230; we can boil SASL down to a few key design elements:</p> <ul> <li>The server proposes, and the client accepts, a &quot;security mechanism&quot;, which is a string.</li> <li>The implementations use the security mechanism to lookup a library that implements it.</li> <li>The server and client exchange challenges and responses, which are binary blobs.</li> <li>These blobs are passed to the security library, which digests them and possibly produces a new challenge or response.</li> <li>Eventually the security library at each side says, &quot;OK, ready&quot;, and the server and client can now communicate.</li> </ul> <p>It's a little more subtle than this, but that's the basic idea. After the two peers shake hands, they can send each other messages encrypted by the security library. Message I/O is still handled by the same code, with the security library acting as a filter (it encodes and decodes messages as needed).</p> <p>What SASL does is pretty magic. First, we can add security mechanisms arbitrarily. The mechanism I want to use for ZMTP is CurveZMQ, but perhaps someone else will make a DTLS mechanism. Remember, each mechanism is a plug in library that doesn't need to know how data gets passed around. It takes blobs, produces blobs, and holds state about the connection. In my <a href="http://hintjens.wikidot.com/blog:36">previous article</a> I showed how a such a filter works.</p> <p>Splitting the security work off makes it much easier to solve. We can test the mechanisms in isolation, before we plug them into real messaging. It also leaves the protocol totally naive about security. That means that as we switch to newer, faster security models, we don't have to change the protocol.</p> <p>A peer announces precisely one security mechanism, unlike SASL, which lets servers announce multiple security mechanisms. Security in ZMTP is <em>assertive</em> in that all peers on a given socket have the same, required level of security. This prevents downgrade attacks and simplifies implementations.</p> <p>When we use this approach, every connection always uses a security mechanism. Of course for most traffic will still be clear text. So ZMTP comes with three mechanisms: NULL (no security), PLAIN (clear text authentication) and CURVE (full security). PLAIN is there for two reasons. One, it provides a decent model for other mechanisms. I'll explain that model in a tick. Two, clear text authentication is pretty useful on internal networks. You don't want that test client connecting to the production server and sending 1M test messages by accident.</p> <h2><span>The NULL Security Mechanism</span></h2> <p>The NULL mechanism is easiest to understand - it gives us pretty much what we already have with ZMTP v2.0. The big difference is that there's an explicit READY command to send metadata (what you'd call &quot;headers&quot; in HTTP). Metadata is one of those things you really, <em>really</em> want to send in an extensible dictionary, since this is where 80% of the experimentation and profit comes from in protocols.</p> <p>In the NULL mechanism, each peer sends off a READY to the other, and can then send or receive messages. They can check each others' metadata, e.g. to validate socket types. If either peer doesn't want to continue it simply closes the connection.</p> <p>There's something about designing protocols to work like real human interactions that pleases me, and feels right. So there's no error reporting in ZMTP. If the peer closes the connection during handshaking, that's a strong rejection (take the hint, and don't connect again!), whereas if the peer closes the connection later, that's a temporary blip (sorry, got distracted, please connect again).</p> <p>Here's the grammar for the NULL mechanism:</p> <div class="code"> <pre><code>null = ready *message ready = command-size &quot;READY &quot; *property property = name value name = OCTET *name-char name-char = ALPHA | DIGIT | &quot;-&quot; | &quot;_&quot; | &quot;.&quot; | &quot;+&quot; value = 4OCTET *OCTET ; Size in network byte order</code></pre></div> <p>Commands always start with a fixed-space 8 character name, and then descend into whatever form of madness makes the command work. For READY, we are sending a metadata dictionary. I decided to go with short text names and long binary values. 2GB should be enough for anyone. This format seems easy to create or parse in any language.</p> <h2><span>The PLAIN Mechanism</span></h2> <p>I'll explain how ZMTP's security works, because if we're going to use this for real work, we need criticism. I've some ideas for encouraging people to try to break the CURVE mechanism, but that's for later.</p> <p>Since I've not finished documenting <a href="http://rfc.zeromq.org/spec:25">CURVE</a>, we'll look at <a href="http://rfc.zeromq.org/spec:24">PLAIN</a>. These two mechanisms <a href="http://rfc.zeromq.org/spec:25">have</a> <a href="http://rfc.zeromq.org/spec:24">RFCs</a> already, and you'll see that they use the precise same command grammar:</p> <div class="code"> <pre><code>C:hello S:welcome C:initiate S:ready *( C:message | S:message )</code></pre></div> <p>This was deliberate. The handshake is synchronous and consists of two requests from the client and two responses from the server. For PLAIN, we could collapse this to one request and one reply. For CURVE it has to be split up, since the initiate-ready step depends on security already established by hello-welcome. (Note that in CurveCP, which is the original design for the CURVE mechanism, the command is called COOKIE, not WELCOME).</p> <p>So conceptually, we have three steps:</p> <ul> <li>Establish security (HELLO, WELCOME).</li> <li>Send meta data (INITIATE, READY).</li> <li>Send messages.</li> </ul> <p>While the first four commands are synchronous, messages are async. That is, the client can start sending messages as soon as it's received READY, and the server can send messages right after it's sent READY. INITIATE and READY carry metadata, like the NULL mechanism's READY command, and using the same dictionary format.</p> <h2><span>The CURVE Mechanism</span></h2> <p>Roughly, the CURVE mechanism works like PLAIN except that it exchanges encryption keys. CURVE in fact implements CurveZMQ, which is a generic security handshake I'm designing that is taken from CurveCP, a UDP-based security and traffic control protocol designed by cryptographer and mathematician <a href="http://cr.yp.to/djb.html">D. J. Bernstein</a>. CurveCP is based on NaCl, the security library from the same djb.</p> <p>The security handshake in CurveCP is elegant and relatively simple (compared to other security designs), and comes with a very good pedigree. Whether it really is as robust as djb claims we won't know for a while. However as well as security, CurveCP aims to replace TCP entirely, doing its own traffic control over UDP.</p> <p>To be honest, I think CurveCP (over UDP) would make a great mechanism in itself for ZMTP but that's a serious challenge. I've tried to keep ZMTP semantically compatible with that idea. In the more pragmatic short term, it turns out that stripping down CurveCP to just the security aspects, assuming TCP is going to be here for some time yet, is feasible.</p> <p>This is CurveZMQ: the CurveCP handshake taken out and stripped down a little. There's a website, curvezmq.org, but it's still empty. My plan is to take material from curvecp.org, and remix that into a single clean RFC.</p> <p>It turns out that it's very useful to do end-to-end security on top of 0MQ, as an alternative to doing security in the library. It means you can route over untrusted peers. Imagine I want to make a secure chat application. Two phones, talking to a server in the middle. We don't want the server to ever get clear text data. So the phones do end-to-end security. If we use security in ZMTP, that won't work.</p> <p>End-to-end security only works with a ROUTER-DEALER combo (or another mix of sockets that can imitate it), since it needs that chatty request-reply handshake. But this is how we build most large-scale services anyhow.</p> <p>Meaning, at some point I'll write a CurveZMQ mechanism in CZMQ, and show how to use this in a protocol like <a href="http://rfc.zeromq.org/spec:19">http://rfc.zeromq.org/spec:19</a> rfc.zeromq.org/spec:19/FILEMQ or <a href="http://rfc.zeromq.org/spec:20">rfc.zeromq.org/spec:20/ZRE</a>.</p> <h2><span>Pluggable Authentication</span></h2> <p>A protocol shouldn't have an opinion on implementations except when it affects how they work together. But as ZeroMQ users we should be asking, &quot;how does my application plug into this security model?&quot;</p> <p>The answer is a little subtle. Clearly as peers come and go, we have to invoke code that authenticates them. ZeroMQ can't do this itself in a realistic way. For instance even the PLAIN mechanism could do a remote username / password lookup to some other server.</p> <p>Our idea is that libzmq provides an inproc socket for authentication and other events. Presumably this would happen on a per-context basis. You then write your authentication logic as a classic ZeroMQ task: connect to a socket, get the events, process them, and send back OK / NOT-OK replies. Meanwhile the &quot;real&quot; application logic continues to run ignorant of the ongoing authentication. It just gets messages and sends messages like today.</p> <h2><span>Connection Metadata</span></h2> <p>Adding a dictionary to the security handshake gives us extensible metadata. Right off, this let me move the socket type and identity out of limbo into a safer home. It also provides a place for more information about the connection.</p> <p>There's really only one reason to put information upfront in the greeting, and that is when we absolutely need it for security negotiation. You'll see one flag (&quot;as-server&quot;) that tells the mechanism whether the peer is acting as client or server. It means we don't need to rely on the bind/connect order. But all other metadata sits in this dictionary.</p> <p>As well as socket type and identity, I defined &quot;resource&quot;, which lets us do virtual addressing.</p> <h2><span>Virtual Addressing</span></h2> <p>One of the missing features in ZMTP was <em>virtual addresses</em>. Physical addresses (TCP endpoints) can be costly in some architectures, e.g. when crossing a firewall. If the protocol provides a place for a peer to request a virtual address, during connection negotiation, we can quite easily allow multiple tasks to bind to the same TCP endpoint.</p> <p>In ZMTP we use the concept of <em>resource</em>, because it fits the schema we already use for zmq_bind and zmq_connect endpoints. Here's how a peer makes a resource available by binding to it:</p> <div class="code"> <pre><code>zmq_bind (publisher, &quot;tcp://*:9001/my/resource/name&quot;);</code></pre></div> <p>Here's how a peer connects to a specific resource on another peer:</p> <div class="code"> <pre><code>zmq_connect (subscriber, &quot;tcp://192.168.55.23:9001/my/resource/name&quot;);</code></pre></div> <p>The implementation will only create one listening TCP socket, but will keep a list of resources available for that listening socket. When a peer connects, the resource it specifies is then used to route messages to the right task.</p> <p>In ZMTP the resource name comes after the security handshake, so it's encrypted and tamper-proof when we use secure mechanisms (I'll come to mechanisms in a second). Putting the resource name <em>after</em> security does have some implications. It means we cannot use the resource to select credentials. In effect, all connections on a physical endpoint must share the same credentials, e.g. the same server keys.</p> <p>This isn't really a limitation since TCP in any case does not allow multiple listeners on a port. It's quite plausible to make a mulitiprocess design in which arbitrary processes on a box share a single physical endpoint, by each specifying a different resource. However, there is going to be a single process that does all the zmq_bind commands, acting as proxy for the other processes. And it's sensible that one process has one set of security credentials.</p> <h2><span>Security Considerations</span></h2> <p>I'll collect possible attacks and strategies to defend against them (if you have more suggestions, let's hear them!) Even attacks we can't defend against are worth documenting. So ZMTP makes some recommendations to implementors:</p> <ul> <li>Attackers may overwhelm a peer by repeated connection attempts. Thus, a peer MAY log failed accesses, and MAY detect and block repeated failed connections from specific originating IP addresses.</li> </ul> <ul> <li>Attackers may try to cause memory exhaustion in a peer by holding open connections. Thus, a peer MAY allocate memory to a connection only after the security handshake is complete, and MAY limit the number and cost of in-progress handshakes.</li> </ul> <ul> <li>Attackers may try to make small requests that generate large responses back to faked originating addresses (the real target of the attack). This is called an &quot;amplification attack&quot;. Thus, peers MAY limit the number of in-progress handshakes per originating IP address.</li> </ul> <ul> <li>Attackers may try to uncover vulnerable versions of an implementation from its metadata. Thus, ZMTP sends metadata <em>after</em> security handshaking.</li> </ul> <ul> <li>Attackers can use the size of messages (even without breaking encryption) to collect information about the meaning. Thus, on an encrypted connection, message data SHOULD be padded to a randomized minimum size.</li> </ul> <ul> <li>Attackers can use the simple presence or absence of traffic to collect information about the peer (&quot;Person X has come on line&quot;). Thus, on an encrypted connection, the peer SHOULD send random garbage data (&quot;noise&quot;) when there is no other traffic. To fully mask traffic, a peer MAY throttle messages so there is no visible difference between noise and real data.</li> </ul> <h2><span>Conclusions</span></h2> <p>We're still some way off from a secure ZeroMQ, but we're seeing the mountain clearly now. The next step is to make simple reference implementations of the core protocol and each mechanism. Then, we can implement the new protocol in libzmq, with some minimal authentication hooks. One step at a time&#8230;</p> <p>So what do you think? Have you tried NaCl or libsodium, and did you like it? Are you more of a DTLS guy, and if so, what do you need to start designing your plugin mechanism for ZMTP/3.0? Are you one of those crazy geniuses who has reimplemented ZMTP/2.0 in Java, C#, Erlang, or Bash? How does this new protocol feel to you? Come and discuss on zeromq-dev.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:38</guid>
				<title>The PUB-SUB Hacks: Census</title>
				<link>http://hintjens.wikidot.com/blog:38</link>
				<description>

&lt;p&gt;In the first article on PUB-SUB hacks, we looked at the Meerkat pattern. In this second article I&#039;ll walk through a pattern—Census—that&#039;s loosely inspired by the &amp;quot;Surveyor&amp;quot; socket type from the defunct Crossroads fork of ZeroMQ. It&#039;s a fairly simple pattern. The code for this article is &lt;a href=&quot;https://gist.github.com/hintjens/5248234&quot;&gt;in a GitHub gist&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 26 Mar 2013 19:28:13 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>In the first article on PUB-SUB hacks, we looked at the Meerkat pattern. In this second article I'll walk through a pattern—Census—that's loosely inspired by the &quot;Surveyor&quot; socket type from the defunct Crossroads fork of ZeroMQ. It's a fairly simple pattern. The code for this article is <a href="https://gist.github.com/hintjens/5248234">in a GitHub gist</a>.</p> <h3><span>The Census Pattern</span></h3> <p>The <strong>Census Pattern</strong> is an evolution of Meerkat that solves the problem of monitoring or querying a set of nodes. The question part looks like a PUB-SUB broadcast and the answer part is similar to a PUSH-PULL sink in that it's a many-to-one flow. You can often simply hard-code the question so it's implied. For instance instead of asking a set of nodes, &quot;who is doing the least work right now?&quot; (to know who to send new work to), nodes could broadcast their availability without being asked.</p> <p>The advantage of explicitly asking the question is, of course, that you can do more sophisticated group queries. For instance, you could send a search pattern to a set of engines, and get back the first reply or all replies. So Census is like group request-reply, where the replies can be processed according to the use-case.</p> <p>Traditionally, we'd design Census using a PUB-SUB pattern for the question, and a PUSH-PULL pattern for the replies. In the old days this the advice we gave ØMQ developers: break a complex pattern into separate flows, use a specific socket type for each one.</p> <p>However it turns out that multiple sets of sockets gets complex and confusing. It's hard to synchronize things when you have multiple independent paths. It's hard to imagine a security model working over mixed socket flows. Using a single socket pair is, it turns out, simpler. And simpler is always better. So that's what we'll aim for: a single socket flow for group request-reply.</p> <p>Don't confuse &quot;censuses&quot; (if that is a proper word) with &quot;surveys&quot;. A census is what you do when you ask your kids, &quot;who wants burgers?&quot; A survey is what you do when you stop random people at the 11th Annual Vegan Life Festival and ask innocently, &quot;who wants burgers?&quot; (The answer might astonish you. Or not. I've never tried, but YouTubing ridiculous surveys conducted on self-selected samples suddenly seems quite fun. Next up, we survey the Papal convention for their opinions on whether burger makes a valid pizza topping, and then we extrapolate their answers to the whole world population.)</p> <p>Popes aside, here are some ground rules for conducting a census:</p> <ul> <li>We generally know in advance how many people we're speaking to. People may come and go randomly but unlike a survey, our goal is to count the heads we can see, not the ones we can't.</li> </ul> <ul> <li>We expect either an answer, or silence, within a certain time. On a computer network as in the real world, there's no such thing as perfection.</li> </ul> <ul> <li>Based on the results, we take some decision, which may be to repeat the question, ask a different question, to jump to a bogus forgone conclusion, etc.</li> </ul> <p>So parameters for a census are: the question we ask, the allowed answers, the time we allow for answers, and the total size of our target population. That last piece is, of course, where Meerkat comes in since it lets us conduct a census of a dynamic population that may be leaving and joining the network randomly.</p> <h4><span>Census Over XPUB-XSUB</span></h4> <p>Clearly the PUB-SUB pattern is a good place to start with a census since we want to broadcast the question to everyone. We do have to use XPUB and XSUB since they give us extra superpowers we need. Two superpowers, in fact:</p> <ul> <li>We can send and receive subscription messages, which lets us do the Meerkat part.</li> </ul> <ul> <li>XSUB sockets can talk back to XPUB sockets, which lets us do the Census part.</li> </ul> <p>John Muehlhausen's <tt>libzmq</tt> <a href="https://github.com/zeromq/libzmq/commit/d32e3922785f170ce24159ab5e4b44badc473ec1">d32e39 commit</a> from 7 January 2013 is worth studying. If I taught computer science, I'd spend a few hours just boring my poor students with this one. His 14-line patch hacked XPUB and XSUB into becoming a two-way highway for messages. It's so simple and so very beautiful. I like the evolution of PUB and SUB from a one-way purist design (from the original one-way PGM-style financial data distribution) into more tactile and pragmatic two-way sockets.</p> <p>The patch is a minimal change, evolution in action. A subscription message starts with 0x01. An unsubscription message starts with 0x00. We discard any other message, right? That's how XPUB and XSUB were <em>designed</em>. But hang on, no, hang on&#8230; Let's not throw other messages away, let's pass them on up instead. Suddenly the gate opens to subscribers sending stuff back to their publishers.</p> <p>So, literally (and I mean this in the non-figurative sense), you can send a &quot;normal&quot; message to an XSUB socket, and you can receive &quot;normal&quot; messages off XPUB sockets. XPUB works like a sink, and will fair-queue incoming messages from its subscribers, while XSUB works like a copier, and will copy the message to each XPUB it's connected to. You don't need any special socket options for this, it's how the sockets work out of the box. If you don't want the functionality, just discard &quot;normal&quot; messages in code that reads from XPUB sockets.</p> <p><strong>Figure 1 - The Census Pattern</strong></p> <div class="image-container aligncenter"><img src="http://hintjens.wdfiles.com/local--files/blog:38/fig1.png" alt="fig1.png" class="image" /></div> <p>Enough ado already, let's take this pie out of the oven and see how it tastes. Here's my first attempt at the Census pattern:</p> <div class="code"> <p><span style="color:#BC7A00"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Census Pattern<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Model 1, over XPUB-XSUB</span></p> <p>#include &quot;czmq.h&quot;</p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span><br /> <span style="color:#0000FF">counter_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args, zctx_t <span style="color:#666666">*</span>ctx, <span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>counter <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_XPUB);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_xpub_verbose (counter, <span style="color:#666666">1</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (counter, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:6001&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The counter task is broken into two steps. First it allows</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>all targets to get ready and raise their hands, using the</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Meerkat pattern. Then it sends out its census question and</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>allows all targets time to reply:</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Parameters for the census</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> count_msec <span style="color:#666666">=</span> <span style="color:#666666">250</span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Msecs to settle down</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> think_msec <span style="color:#666666">=</span> <span style="color:#666666">250</span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Msecs for responses</em></span></p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Calling thread tells us the population size</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>population <span style="color:#666666">=</span> zstr_recv (pipe);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>All activity happens on our counter socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zmq_pollitem_t items <span style="white-space: pre-wrap;">[]</span> <span style="color:#666666">=</span> { { counter, <span style="color:#666666">0</span>, ZMQ_POLLIN, <span style="color:#666666">0</span> } };<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>byte meerkat <span style="white-space: pre-wrap;">[]</span> <span style="color:#666666">=</span> { <span style="color:#666666">1</span>, <span style="color:#BA2121">'M'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'r'</span>, <span style="color:#BA2121">'k'</span>, <span style="color:#BA2121">'a'</span>, <span style="color:#BA2121">'t'</span> };<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Both steps are zmq_poll loops which exit either when we</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>get the expected number of responses, or we time-out. In</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>the first step we count only Meerkat subscriptions:</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> headcount <span style="color:#666666">=</span> <span style="color:#666666">0</span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Known target size</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int64_t</span> timer_end <span style="color:#666666">=</span> zclock_time () <span style="color:#666666">+</span> count_msec;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> still_waiting <span style="color:#666666">=</span> atoi (population);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (still_waiting) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int64_t</span> time_left <span style="color:#666666">=</span> timer_end <span style="color:#666666">-</span> zclock_time ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (time_left <span style="color:#666666">&lt;=</span> <span style="color:#666666">0</span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We're done here</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zmq_poll (items, <span style="color:#666666">1</span>, time_left <span style="color:#666666">*</span> ZMQ_POLL_MSEC);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (rc <span style="color:#666666">==</span> <span style="color:#666666">-</span><span style="color:#666666">1</span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Interrupted</em></span></p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (items <span style="white-space: pre-wrap;">[</span><span style="color:#666666">0</span><span style="white-space: pre-wrap;">]</span>.revents <span style="color:#666666">&amp;</span> ZMQ_POLLIN) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_t <span style="color:#666666">*</span>frame <span style="color:#666666">=</span> zframe_recv (counter);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (<span style="color:#666666">!</span>frame)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Interrupted</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (zframe_size (frame) <span style="color:#666666">==</span> <span style="color:#008000"><strong>sizeof</strong></span> (meerkat)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#666666">&amp;&amp;</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>memcmp (zframe_data (frame), meerkat,<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>sizeof</strong></span> (meerkat)) <span style="color:#666666">==</span> <span style="color:#666666">0</span>) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>still_waiting<span style="color:#666666"><span style="white-space: pre-wrap;">--</span></span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>headcount<span style="color:#666666">++</span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_destroy (<span style="color:#666666">&amp;</span>frame);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Now we've got our target population and we know they're</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>subscribed, we send out the census question:</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (counter, <span style="color:#BA2121">&quot;Who wants pizza?&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>In the second poll loop, we wait for valid answers to our</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>census question. We might still receive subscription</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>messages so we have to discount those:</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> positives <span style="color:#666666">=</span> <span style="color:#666666">0</span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>How many said &quot;yes&quot;</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>timer_end <span style="color:#666666">=</span> zclock_time () <span style="color:#666666">+</span> think_msec;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>still_waiting <span style="color:#666666">=</span> headcount;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (still_waiting) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int64_t</span> time_left <span style="color:#666666">=</span> timer_end <span style="color:#666666">-</span> zclock_time ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (time_left <span style="color:#666666">&lt;=</span> <span style="color:#666666">0</span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We're done here</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zmq_poll (items, <span style="color:#666666">1</span>, time_left <span style="color:#666666">*</span> ZMQ_POLL_MSEC);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (rc <span style="color:#666666">==</span> <span style="color:#666666">-</span><span style="color:#666666">1</span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Interrupted</em></span></p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (items <span style="white-space: pre-wrap;">[</span><span style="color:#666666">0</span><span style="white-space: pre-wrap;">]</span>.revents <span style="color:#666666">&amp;</span> ZMQ_POLLIN) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_t <span style="color:#666666">*</span>frame <span style="color:#666666">=</span> zframe_recv (counter);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (<span style="color:#666666">!</span>frame)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Interrupted</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>byte <span style="color:#666666">*</span>data <span style="color:#666666">=</span> zframe_data (frame);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Ignore any subscriptions we might still get</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (data <span style="white-space: pre-wrap;">[</span><span style="color:#666666">0</span><span style="white-space: pre-wrap;">]</span> <span style="color:#666666">&gt;</span> <span style="color:#666666">1</span>) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (streq ((<span style="color:#B00040">char</span> <span style="color:#666666">*</span>) data, <span style="color:#BA2121">&quot;Yes&quot;</span>))<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>positives<span style="color:#666666">++</span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>still_waiting<span style="color:#666666"><span style="white-space: pre-wrap;">--</span></span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_destroy (<span style="color:#666666">&amp;</span>frame);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>printf (<span style="color:#BA2121">&quot;Out of %d people, %d want pizza</span><span style="color:#BB6622"><strong>\n</strong></span><span style="color:#BA2121">&quot;</span>, headcount, positives);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (pipe, <span style="color:#BA2121">&quot;DONE&quot;</span>);<br /> }</p> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The target task starts by doing a Meerkat subscription, and then<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>subscribes to everything with a zero-sized subscription message.<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>It waits for the census question and answers Yes or No randomly:</span></span></p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span><br /> <span style="color:#0000FF">target_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args, zctx_t <span style="color:#666666">*</span>ctx, <span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>target <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_XSUB);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (target, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>localhost:6001&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Tell publisher we're here</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>byte meerkat <span style="white-space: pre-wrap;">[]</span> <span style="color:#666666">=</span> { <span style="color:#666666">1</span>, <span style="color:#BA2121">'M'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'r'</span>, <span style="color:#BA2121">'k'</span>, <span style="color:#BA2121">'a'</span>, <span style="color:#BA2121">'t'</span> };<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zmq_send (target, <span style="color:#666666">&amp;</span>meerkat, <span style="color:#008000"><strong>sizeof</strong></span> (meerkat), <span style="color:#666666">0</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Subscribe to everything as well (empty subscription)</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zmq_send (target, <span style="color:#666666">&amp;</span>meerkat, <span style="color:#666666">1</span>, <span style="color:#666666">0</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>question <span style="color:#666666">=</span> zstr_recv (target);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>answer <span style="color:#666666">=</span> randof (<span style="color:#666666">2</span>) <span style="color:#666666">==</span> <span style="color:#666666">0</span><span style="color:#666666">?</span> <span style="color:#BA2121">&quot;Yes&quot;</span><span style="color:#666666">:</span> <span style="color:#BA2121">&quot;No&quot;</span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>printf (<span style="color:#BA2121">&quot;%s %s</span><span style="color:#BB6622"><strong>\n</strong></span><span style="color:#BA2121">&quot;</span>, question, answer);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (question);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (target, answer);<br /> }</p> <p><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The main task starts a counter task and a set of target tasks:</em></span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_t <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Size of target population</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>srand ((<span style="color:#B00040">unsigned</span>) time (<span style="color:#008000">NULL</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> population <span style="color:#666666">=</span> randof (<span style="color:#666666">10</span>) <span style="color:#666666">+</span> <span style="color:#666666">1</span>;</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start counter task</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe <span style="color:#666666">=</span> zthread_fork (ctx, counter_task, <span style="color:#008000">NULL</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (pipe, <span style="color:#BA2121">&quot;%d&quot;</span>, population);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start target population</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (population<span style="color:#666666"><span style="white-space: pre-wrap;">--</span></span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zthread_fork (ctx, target_task, <span style="color:#008000">NULL</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Wait for census to complete</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (zstr_recv (pipe));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>census1.c: Census Pattern over XSUB-XPUB</em> <p>It's not huge, 150 lines of code in C. The counter task has two steps. If all nodes are up and running, the whole thing runs with no delay. If there's a node broken or too busy to answer, each step will wait for a while before timing out. A census will still be valid if there are missing nodes. In a realistic implementation we could continue to ask more questions, and not need to wait for nodes to join again each time.</p> <h4><span>Census Over ROUTER-DEALER</span></h4> <p>In the Big Black Book of Mad Science (originally it was a kind of light green but multiple incendiary near-misses gave it a charred exterior, and the general consensus was that &quot;The Big Kind of Light Green Book&quot; didn't have quite the same ring anyhow), rule number three is: &quot;If at first you succeed, try again with more gunpowder&quot;. (Rules one and two are, since you're asking, &quot;Bald is the new Evil&quot;, and &quot;If you laugh loudly, you can get away with almost anything&quot;. Protective eye-wear only merits rule number 24. Rule number five says, enigmatically, &quot;If you have to ask what rule #5 is, you can't afford it.&quot;)</p> <p>So, more gunpowder! XPUB-XSUB is neat, but how about ROUTER-DEALER? After all, the Census pattern requires a two-way many-to-one dialog, and ROUTER-DEALER are pretty good at that. As an experiment, let's rewrite the same Census example using ROUTER-DEALER, and see whether it's simpler or more complex.</p> <p><strong>Figure 2 - Census with More Gunpowder</strong></p> <div class="image-container aligncenter"><img src="http://hintjens.wdfiles.com/local--files/blog:38/fig2.png" alt="fig2.png" class="image" /></div> <p>Here's the code:</p> <div class="code"> <p><span style="color:#BC7A00"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Census Pattern<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Model 2, over ROUTER-DEALER</span></p> <p>#include &quot;czmq.h&quot;</p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span><br /> <span style="color:#0000FF">counter_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args, zctx_t <span style="color:#666666">*</span>ctx, <span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>counter <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_ROUTER);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (counter, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:6001&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Parameters for the census</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> census_msec <span style="color:#666666">=</span> <span style="color:#666666">250</span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Msecs to settle down</em></span></p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Calling thread tells us the population size</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>population <span style="color:#666666">=</span> zstr_recv (pipe);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>All activity happens on our counter socket</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zmq_pollitem_t items <span style="white-space: pre-wrap;">[]</span> <span style="color:#666666">=</span> { { counter, <span style="color:#666666">0</span>, ZMQ_POLLIN, <span style="color:#666666">0</span> } };</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> headcount <span style="color:#666666">=</span> <span style="color:#666666">0</span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Known target size</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> positives <span style="color:#666666">=</span> <span style="color:#666666">0</span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>How many said &quot;yes&quot;</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int64_t</span> timer_end <span style="color:#666666">=</span> zclock_time () <span style="color:#666666">+</span> census_msec;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> still_waiting <span style="color:#666666">=</span> atoi (population);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (still_waiting) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int64_t</span> time_left <span style="color:#666666">=</span> timer_end <span style="color:#666666">-</span> zclock_time ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (time_left <span style="color:#666666">&lt;=</span> <span style="color:#666666">0</span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>We're done here</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> rc <span style="color:#666666">=</span> zmq_poll (items, <span style="color:#666666">1</span>, time_left <span style="color:#666666">*</span> ZMQ_POLL_MSEC);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (rc <span style="color:#666666">==</span> <span style="color:#666666">-</span><span style="color:#666666">1</span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Interrupted</em></span></p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (items <span style="white-space: pre-wrap;">[</span><span style="color:#666666">0</span><span style="white-space: pre-wrap;">]</span>.revents <span style="color:#666666">&amp;</span> ZMQ_POLLIN) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_t <span style="color:#666666">*</span>address <span style="color:#666666">=</span> zframe_recv (counter);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>message <span style="color:#666666">=</span> zstr_recv (counter);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (streq (message, <span style="color:#BA2121">&quot;Hello&quot;</span>)) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>headcount<span style="color:#666666">++</span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_send (<span style="color:#666666">&amp;</span>address, counter, ZFRAME_MORE);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zstr_send (counter, <span style="color:#BA2121">&quot;Who wants pizza?&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>else</strong></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (streq (message, <span style="color:#BA2121">&quot;Yes&quot;</span>))<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>positives<span style="color:#666666">++</span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_destroy (<span style="color:#666666">&amp;</span>address);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>free (message);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>printf (<span style="color:#BA2121">&quot;Out of %d people, %d want pizza</span><span style="color:#BB6622"><strong>\n</strong></span><span style="color:#BA2121">&quot;</span>, headcount, positives);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (pipe, <span style="color:#BA2121">&quot;DONE&quot;</span>);<br /> }</p> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The target task starts by saying Hello, then it waits for the<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>census question and answers Yes or No randomly:</span></span></p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span><br /> <span style="color:#0000FF">target_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args, zctx_t <span style="color:#666666">*</span>ctx, <span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>subscriber <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_DEALER);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (subscriber, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>localhost:6001&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (subscriber, <span style="color:#BA2121">&quot;Hello&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>question <span style="color:#666666">=</span> zstr_recv (subscriber);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>answer <span style="color:#666666">=</span> randof (<span style="color:#666666">2</span>) <span style="color:#666666">==</span> <span style="color:#666666">0</span><span style="color:#666666">?</span> <span style="color:#BA2121">&quot;Yes&quot;</span><span style="color:#666666">:</span> <span style="color:#BA2121">&quot;No&quot;</span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>printf (<span style="color:#BA2121">&quot;%s %s</span><span style="color:#BB6622"><strong>\n</strong></span><span style="color:#BA2121">&quot;</span>, question, answer);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (question);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (subscriber, answer);<br /> }</p> <p><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The main task starts a counter task and a set of target tasks:</em></span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_t <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Size of target population</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>srand ((<span style="color:#B00040">unsigned</span>) time (<span style="color:#008000">NULL</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> population <span style="color:#666666">=</span> randof (<span style="color:#666666">10</span>) <span style="color:#666666">+</span> <span style="color:#666666">1</span>;</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start counter task</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe <span style="color:#666666">=</span> zthread_fork (ctx, counter_task, <span style="color:#008000">NULL</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (pipe, <span style="color:#BA2121">&quot;%d&quot;</span>, population);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start target population</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (population<span style="color:#666666"><span style="white-space: pre-wrap;">--</span></span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zthread_fork (ctx, target_task, <span style="color:#008000">NULL</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Wait for census to complete</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (zstr_recv (pipe));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>census2.c: Census Pattern over ROUTER-DEALER</em> <p>Quite shockingly, this worked first time and is only two-thirds the size of the XPUB-XSUB version. The code is quite a lot simpler. This teaches us a few things:</p> <ul> <li>ROUTER-DEALER is a powerful tool.</li> </ul> <ul> <li>Asynchronous beats synchronous. The main cost in the XPUB-XSUB model is the getting everyone to pay attention and listen to the question at the same time. This doubles the size of the publisher task and doubles the worst-case time for the census.</li> </ul> <ul> <li>Always try again, with more gunpowder.</li> </ul> <p>The next and final article in this little series of PUB-SUB Hacks will cover the Repeater pattern, which is an &quot;any-to-all pub-sub for Very Large Networks&quot; pattern.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:37</guid>
				<title>The PUB-SUB Hacks: Meerkat</title>
				<link>http://hintjens.wikidot.com/blog:37</link>
				<description>

&lt;p&gt;While the ØMQ pub-sub pattern is well-known for being a one-way pattern, it does in fact support a two-way flow of information. SUB sockets (or more accurately, XSUB sockets) can send messages to XPUB sockets. This week, I&#039;ll post a series of short articles that cover different patterns—Meerkat, Census, and Repeater—we can build using this functionality. As usual, I&#039;ll demonstrate each pattern with code you can download and run.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 26 Mar 2013 18:44:39 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>While the ØMQ pub-sub pattern is well-known for being a one-way pattern, it does in fact support a two-way flow of information. SUB sockets (or more accurately, XSUB sockets) can send messages to XPUB sockets. This week, I'll post a series of short articles that cover different patterns—Meerkat, Census, and Repeater—we can build using this functionality. As usual, I'll demonstrate each pattern with code you can download and run.</p> <h3><span>The Meerkat Pattern</span></h3> <p>One of the common questions from ØMQ developers (until they learn that there's no good answer and retreat into a kind of Stockholmesque &quot;if it hurts it must be for our own good&quot; acceptance) is &quot;how can a publisher know when subscribers are present?&quot; However as I've written elsewhere, pain is not a good sign.</p> <p>It is true that for certain use cases, the answer is, &quot;you don't want to know&quot;. It's true that for very large scale publishers, the raw cost of tracking individual subscribers in real time is not worth the effort. The BBC doesn't wait until everyone's ready with their telly before starting Blue Peter. So, the argument goes, why should we?</p> <p>But I'm suspicious of people who tell me what I should think. Particularly since, as a writer, propaganda is <em>my job</em>. And I know just how much rubbish people say when they're being especially serious. But kidding aside, the question is valid, and the &quot;no, you don't want to do this&quot; answer seems bogus and somewhat lazy. We know that publishers can benefit greatly from tracking individual subscribers. This was after all the major improvement in version 3 of ØMQ: much faster PUB-SUB thanks to &quot;upstreaming&quot;, where subscribers actually tell publishers what data they want.</p> <p>If it's good for XPUB and XSUB sockets, why not for applications too? This was the question that innocently entered my mind one spring morning in Brussels, as we watched yet another snowstorm unfold. Innocence is all relative, of course, as they say in Rome. The question hooked into some unfinished thoughts and formed a flash mob of irritation that forced me to stop working briefly on more interesting topics. The <strong>Meerkat Pattern</strong> is what came out.</p> <div class="image-container floatright"><a href="http://hintjens.wdfiles.com/local--files/blog:37/meerkats.jpg"><img src="http://hintjens.wdfiles.com/local--resized-images/blog:37/meerkats.jpg/small.jpg" alt="meerkats.jpg" class="image" /></a></div> <p>This is one of the real pleasures of using a technology: to twist and distort it into shapes its original designers never thought of, and see what comes out. So let's distort and abuse the XPUB-XSUB upstreaming functionality to answer that question and give publishers a way to know what subscribers are around.</p> <p>I once had a friend and mentor, the larger-than-life Leif Svalgaard, who would work secretly on some amazing code and then show the finished results to general astonishment. When we asked him how he did it, he invariably answered with a huge Santa Clause grin, palms up innocently, saying, &quot;it's magic!&quot; Once Leif wrote a tiny but working multitasking system for DOS over the weekend, just to disprove Microsoft's claims that OS/2 (yes, this was some time ago) needed 8 Megabytes of memory &quot;because it did multitasking&quot;. As he started a compilation in one window, and edited a file in another, I asked him, &quot;how did you do this?&quot; &quot;Ah, it's magic!&quot; he answered.</p> <p>Incidentally, that tiny multitasking system (1,000 lines of x86 assembly) inspired my multithreading SMT kernel in 1995, which became the heart of our server technology and then OpenAMQ, which led the way to ZeroMQ. So it goes in the history of software, a chain of inspiration and culture leading back to the first time primitive man told his wife, &quot;just going down to the cave to paint some pr0&#8230; ugh&#8230; hunting scenes, honey. BRB!&quot;</p> <p><strong>Figure 1 - The Meerkat Pattern</strong></p> <div class="image-container aligncenter"><img src="http://hintjens.wdfiles.com/local--files/blog:37/fig1.png" alt="fig1.png" class="image" /></div> <h4><span>Step 1: Counting Subscriptions</span></h4> <p>What if a publisher (suitably wearing an &quot;X&quot; on its torso to mark it with XPUB superpowers) simply counted the number of subscriptions it received? Perhaps surprisingly, this works for all values of N on the condition that N is equal to one. To say this in English, an XPUB tracks subscriptions and only tells you of the first one. So, on to attempt 2.</p> <h4><span>Step 2: Using the Verbose Option</span></h4> <p>A few months ago we added a neat little option (ZMQ_XPUB_VERBOSE) to XPUB sockets that disables its filtering of duplicate subscriptions. This now works for any number of subscribers. We use this as follows:</p> <div class="code"> <p><span style="color:#B00040">void</span> <span style="color:#666666">*</span>publisher <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_XPUB);<br /> zsocket_set_xpub_verbose (publisher, <span style="color:#666666">1</span>);<br /> zsocket_bind (publisher, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:6001&quot;</span>);</p> </div> <br /> <em>fragments/xpub-verbose-option.c: Listing 1</em> <p>However we still have a problem. Subscribers may subscribe any number of times. We need some devious trick to distinguish different kinds of subscriptions.</p> <h4><span>Step 3: Sending 'Special' Subscriptions</span></h4> <p>My first idea was to use the empty subscription, but of course this doesn't play well with real use. Let's say I have two subscribers that subscribe to a series of topics:</p> <ul> <li>A subscribes to &quot;USD&quot;, &quot;JPY&quot;, and &quot;EUR&quot;</li> <li>B subscribes to &quot;JPY&quot; and &quot;KRW&quot;</li> </ul> <p>How do I know how many subscribers I have?</p> <p>My answer, which is not very beautiful but works, is to send a &quot;special&quot; subscription that doesn't match any real data but which tells my application what it needs to know:</p> <ul> <li>A subscribes to &quot;USD&quot;, &quot;JPY&quot;, &quot;EUR&quot;, and &quot;Meerkat&quot;</li> <li>B subscribes to &quot;JPY&quot;, &quot;KRW&quot;, and &quot;Meerkat&quot;</li> </ul> <p>So this brings us to an example of Meerkat in action:</p> <div class="code"> <p><span style="color:#BC7A00"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The Meerkat Pattern<br /> <span style="white-space: pre-wrap;">//</span><br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>In which we address the slow subscriber problem by asking for<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>a show of hands before we start publishing.</span></p> <p>#include &quot;czmq.h&quot;</p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span><br /> <span style="color:#0000FF">publisher_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args, zctx_t <span style="color:#666666">*</span>ctx, <span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_set_linger (ctx, <span style="color:#666666">1000</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>publisher <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_XPUB);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_set_xpub_verbose (publisher, <span style="color:#666666">1</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_bind (publisher, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>*:6001&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Calling thread tells us the population size</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>population <span style="color:#666666">=</span> zstr_recv (pipe);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> still_waiting <span style="color:#666666">=</span> atoi (population);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>byte meerkat <span style="white-space: pre-wrap;">[]</span> <span style="color:#666666">=</span> { <span style="color:#666666">1</span>, <span style="color:#BA2121">'M'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'r'</span>, <span style="color:#BA2121">'k'</span>, <span style="color:#BA2121">'a'</span>, <span style="color:#BA2121">'t'</span> };<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (still_waiting) {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_t <span style="color:#666666">*</span>frame <span style="color:#666666">=</span> zframe_recv (publisher);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (<span style="color:#666666">!</span>frame)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>break</strong></span>;<tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Interrupted</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>if</strong></span> (zframe_size (frame) <span style="color:#666666">==</span> <span style="color:#008000"><strong>sizeof</strong></span> (meerkat)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#666666">&amp;&amp;</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>memcmp (zframe_data (frame), meerkat, <span style="color:#008000"><strong>sizeof</strong></span> (meerkat)) <span style="color:#666666">==</span> <span style="color:#666666">0</span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>still_waiting<span style="color:#666666"><span style="white-space: pre-wrap;">--</span></span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Dump the frame contents for the benefit of the reader</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_print (frame, <span style="color:#008000">NULL</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zframe_destroy (<span style="color:#666666">&amp;</span>frame);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span>}</tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Now broadcast our message</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (publisher, <span style="color:#BA2121">&quot;Hello, World!&quot;</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zclock_sleep (<span style="color:#666666">250</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (pipe, <span style="color:#BA2121">&quot;DONE&quot;</span>);<br /> }</p> <p><span style="color:#408080"><span style="font-style:italic"><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The subscriber sends a &quot;Meerkat&quot; subscription and then<br /> <span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>any other subscriptions it wants:</span></span></p> <p><span style="color:#008000"><strong>static</strong></span> <span style="color:#B00040">void</span><br /> <span style="color:#0000FF">subscriber_task</span> (<span style="color:#B00040">void</span> <span style="color:#666666">*</span>args, zctx_t <span style="color:#666666">*</span>ctx, <span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>subscriber <span style="color:#666666">=</span> zsocket_new (ctx, ZMQ_XSUB);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zsocket_connect (subscriber, <span style="color:#BA2121">&quot;tcp:<span style="white-space: pre-wrap;">//</span>localhost:6001&quot;</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Tell publisher we're here</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>byte meerkat <span style="white-space: pre-wrap;">[]</span> <span style="color:#666666">=</span> { <span style="color:#666666">1</span>, <span style="color:#BA2121">'M'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'e'</span>, <span style="color:#BA2121">'r'</span>, <span style="color:#BA2121">'k'</span>, <span style="color:#BA2121">'a'</span>, <span style="color:#BA2121">'t'</span> };<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zmq_send (subscriber, <span style="color:#666666">&amp;</span>meerkat, <span style="color:#008000"><strong>sizeof</strong></span> (meerkat), <span style="color:#666666">0</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Subscribe to everything as well (empty subscription)</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zmq_send (subscriber, <span style="color:#666666">&amp;</span>meerkat, <span style="color:#666666">1</span>, <span style="color:#666666">0</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">char</span> <span style="color:#666666">*</span>hello <span style="color:#666666">=</span> zstr_recv (subscriber);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>puts (hello);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (hello);<br /> }</p> <p><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>The main task starts publisher task and then the subscribers:</em></span></p> <p><span style="color:#B00040">int</span> <span style="color:#0000FF">main</span> (<span style="color:#B00040">void</span>)<br /> {<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_t <span style="color:#666666">*</span>ctx <span style="color:#666666">=</span> zctx_new ();</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Size of target population</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>srand ((<span style="color:#B00040">unsigned</span>) time (<span style="color:#008000">NULL</span>));<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">int</span> population <span style="color:#666666">=</span> randof (<span style="color:#666666">10</span>) <span style="color:#666666">+</span> <span style="color:#666666">1</span>;<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start publisher task</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#B00040">void</span> <span style="color:#666666">*</span>pipe <span style="color:#666666">=</span> zthread_fork (ctx, publisher_task, <span style="color:#008000">NULL</span>);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zstr_send (pipe, <span style="color:#BA2121">&quot;%d&quot;</span>, population);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Start target population</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>while</strong></span> (population<span style="color:#666666"><span style="white-space: pre-wrap;">--</span></span>)<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;</span></tt>zthread_fork (ctx, subscriber_task, <span style="color:#008000">NULL</span>);</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#408080"><em><span style="white-space: pre-wrap;">//</span><tt><span style="white-space: pre-wrap;">&#32;&#32;</span></tt>Wait for publisher to complete</em></span><br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>free (zstr_recv (pipe));</p> <p><tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt>zctx_destroy (<span style="color:#666666">&amp;</span>ctx);<br /> <tt><span style="white-space: pre-wrap;">&#32;&#32;&#32;&#32;</span></tt><span style="color:#008000"><strong>return</strong></span> <span style="color:#666666">0</span>;<br /> }</p> </div> <br /> <em>meerkat.c: Meerkat Pattern</em> <p><a href="https://gist.github.com/hintjens/5248065">Get the code.</a></p> <p>When you run this code you'll see it starts a random number of subscribers, waits until they all wake up, and then sends &quot;Hello, World&quot; to everyone.</p> <h4><span>Step 4: Ridiculous Optimization</span></h4> <p>If you look a little closer at the code you'll see a possible optimization. Instead of sending a <em>subscription</em> message to signal presence, how about an <em>unsubscription</em> message?</p> <p>It's a great idea except (at time of writing), XPUB sockets don't verbosely send you unsubscribe messages. There are reasons for this (there are <em>always</em> reasons, he said darkly, to no-one in particular) but it's minor. Perfection is, sometimes, just a waste of time, and sending subscribe messages seems fine.</p> <h4><span>Step 5: Robustness</span></h4> <p>The Meerkat example will occasionally fail in the real world because it doesn't distinguish between a subscriber saying &quot;I'm here&quot; for the first time from one who comes back several times. We're basically counting the heads that pop-up, not the bodies that are really present on the field. The same head can pop-up over and over, and like idiots we'll count it multiple times.</p> <p>There's an answer—there always is—but it makes things more complex. Each subscriber has to identify itself uniquely and the server has to track this. Subscribers could for instance send a UUID as part of their &quot;special&quot; subscription. The server would track these in a hash table, and count only new entries.</p> <p>It's the kind of boring grunt work we invented ØMQ to get away from, so I'm not going to feed you an example. Let's just agree that making things more complex is easy. My next article will cover the Census pattern, which extends Meerkat into a group query pattern.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:36</guid>
				<title>Securing ZeroMQ: CurveZMQ protocol and implementation</title>
				<link>http://hintjens.wikidot.com/blog:36</link>
				<description>

&lt;p&gt;This week, we flesh out the basics of our CurveCP-derived protocol, with an implementation in C that I&#039;m calling CurveZMQ. In this article I&#039;ll explain what this simple but powerful security protocol looks like. The code here will already work over 0MQ sockets but our next stage is to move this into libzmq itself, for all sockets over &lt;tt&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;tcp://&lt;/span&gt;&lt;/tt&gt; and &lt;tt&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt;ipc://&lt;/span&gt;&lt;/tt&gt;. So stay tuned!&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 22 Mar 2013 22:19:20 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>This week, we flesh out the basics of our CurveCP-derived protocol, with an implementation in C that I'm calling CurveZMQ. In this article I'll explain what this simple but powerful security protocol looks like. The code here will already work over 0MQ sockets but our next stage is to move this into libzmq itself, for all sockets over <tt><span style="white-space: pre-wrap;">tcp://</span></tt> and <tt><span style="white-space: pre-wrap;">ipc://</span></tt>. So stay tuned!</p> <h2><span>Overview of CurveZMQ</span></h2> <p><a href="https://gist.github.com/hintjens/5224958">The CurveZMQ code</a> uses the <a href="http://rfc.zeromq.org/spec:21">CLASS</a> conventions which make the C code look like something nicer. Here's the self-test code, which sends &quot;Hello&quot; and expects &quot;World&quot; back. CurveZMQ uses a single module, <tt>zcurve</tt>:</p> <div class="code"> <pre><code>zmq_msg_t *msg; // Start server peer zcurve_t *server = zcurve_new (); msg = zcurve_start (server, NULL); assert (msg == NULL); // Start client peer and ping/pong through the handshake zcurve_t *client = zcurve_new (); msg = zcurve_start (client, zcurve_public_key (server)); while (msg) { // Send encoded message from client to server // ... // Receive encoded message in server msg = zcurve_accept (server, msg); if (msg) // Send encoded message from server to client // ... // Receive encoded message in client msg = zcurve_accept (client, msg); } msg = zcurve_encode (client, (byte *) &quot;Hello&quot;, 5); assert (msg); // Send encoded message over the wire // ... // Receive encoded message from the wire msg = zcurve_accept (server, msg); assert (msg); assert (memcmp (zmq_msg_data (msg), &quot;Hello&quot;, 5) == 0); msg = zcurve_encode (server, (byte *) &quot;World&quot;, 5); assert (msg); // Send encoded message over the wire // ... // Receive encoded message from the wire msg = zcurve_accept (client, msg); assert (msg); assert (memcmp (zmq_msg_data (msg), &quot;World&quot;, 5) == 0); zcurve_destroy (&amp;server); zcurve_destroy (&amp;client);</code></pre></div> <p>We work with two zcurve instances; one acts as client and one as server. In practice you'd create a zcurve instance for each 1-to-1 connection. The security protocol, which I'll explain, assumes that the underlying transport is TCP. There's an easy tweak to make this work over disconnected protocols (PGM, UDP, or even non-network protocols like shared disk). But since that isn't our use case, I'll explain the tweak and then forget about it.</p> <p>The zcurve API reminds us a little of SASL, with its &quot;I'll consume and produce opaque blobs until I'm satisfied&quot;. The blobs in our case are 0MQ messages. In the test code above we don't send them anywhere, we simply pass them between two zcurve instances until the handshaking is done. There are three critical methods in the API:</p> <ul> <li><tt>zcurve_start ()</tt> - which starts the state machine and may issue a challenge command.</li> <li><tt>zcurve_accept ()</tt> - which accepts a command and may issue a response.</li> <li><tt>zcurve_encode ()</tt> - which turns a plain text payload into an encoded blob.</li> </ul> <p>In fact the API still needs work: right now the accept method's response message does double duty. If we're still handshaking, it has to go back to the peer. If we're finished hand-shaking, it's a decoded payload. I'll fix this in the next prototype.</p> <p>But one step at a time. <em>Don't make stuff you don't need.</em> This brings me to the CurveZMQ protocol, which is derived from <a href="http://curvecp.org">the CurveCP handshake</a> and uses the same concepts like cookies, nonces, and vouches, but is simpler. The original CurveCP handshake is designed for UDP and includes a variety of non-security related features like virtual hosts. Trimming off this and other unnecessary fields gives us a minimal Curve-derived protocol.</p> <p>The zcurve module uses a state machine to decide what's valid and what's not. In this prototype, anything invalid causes an assertion failure. It is not meant to be production code, yet. In practice invalid messages will cause the connection to be dropped.</p> <h2><span>Building and Testing</span></h2> <p>To build this you first want to install and build <a href="https://github.com/jedisct1/libsodium">libsodium</a>. Use the standard commands:</p> <div class="code"> <pre><code>./configure make &amp;&amp; make check &amp;&amp; make install</code></pre></div> <p>You also want libzmq and CZMQ. Then take <a href="https://gist.github.com/hintjens/5224958">the CurveZMQ code from the gist</a> and compile and link zcurve_test:</p> <div class="code"> <pre><code>git clone https://gist.github.com/5224958.git CurveZMQ cd CurveZMQ gcc -g -o zcurve_test zcurve_test.c zcurve.c -lczmq -lzmq -lsodium</code></pre></div> <p>And run the test program:</p> <div class="code"> <pre><code>$ ./zcurve_test Running self tests... * zcurve: C:HELLO: OK S:COOKIE: OK C:INITIATE: OK -:MESSAGE: OK -:MESSAGE: OK Tests passed OK</code></pre></div> <h2><span>Security Models</span></h2> <p>CurveZMQ allows three possible security models:</p> <ul> <li>Anonymous clients, known server: where the server key is known to clients, but the server does not validate client keys.</li> <li>Pre-shared clients, known server: where the server key is known to clients, and all clients share a single key.</li> <li>Fully authenticated: where the full set of allowed clients is known to the server.</li> </ul> <p>We don't yet have a hook in zcurve to authenticate a client; it would be trivial to add, e.g. using a callback that checks a given client long-term public key.</p> <h2><span>Differences between CurveZMQ and the CurveCP Handshake</span></h2> <p>To understand this section you should at least briefly read <a href="http://curvecp.org">the CurveCP website</a> and protocol description.</p> <p>While CurveCP runs over UDP and uses a number of techniques to harden the server (such as not allocating memory until the client has successfully echoed a cookie), CurveZMQ runs over a connected transport (TCP or IPC) and cannot use, and does not need all the functionality of CurveCP:</p> <ul> <li><em>We do not use a minute key for cookies</em>; instead, each connection creates a unique cookie key which is valid until the client sends an INITIATE command. The server could also check that INITIATE comes within 60 seconds of HELLO.</li> </ul> <ul> <li><em>We do not send the client short-term key in MESSAGE commands</em>. This would be useful over disconnected transports but for our use case, TCP and IPC, it's pointless. If we added that, we'd add it both for client and server MESSAGE commands, so that clients could work with multiple servers.</li> </ul> <ul> <li>For simplicity, <em>INITIATE does not contain message data.</em></li> </ul> <ul> <li>Thus, <em>server and client MESSAGE commands have the same structure</em> and are the only carriers for payloads.</li> </ul> <ul> <li><em>We don't have a hostname in the INITIATE command.</em></li> </ul> <p>And we don't use any of the CurveCP traffic control protocol fields. CurveZMQ assumes a reliable connected transport.</p> <p>The current CurveZMQ prototype still uses a fixed message size, maximum of 100 bytes. The next iteration will need variable message encoding. There are a number of other simplifications that are more or less safe:</p> <ul> <li><em>Long term server nonces are not segregated</em> but we'd want to do this in practice: start the server nonce at a random number and then increment by 1.</li> </ul> <ul> <li><em>Short term nonces are always generated from random numbers.</em> The chance of a collision is low enough that this is robust for production use.</li> </ul> <h2><span>CurveZMQ Internals</span></h2> <p>Here are the command structures we use. I'll document the detailed specification of each field later; the CurveCP website does explain them already:</p> <div class="code"> <pre><code>typedef struct { byte id [8]; // Command ID byte cn_client [32]; // Client short-term public key C' byte cn_nonce [8]; // Client short-term nonce byte box [80]; // Box [64 * %x0](C'-&gt;S) byte padding [64]; // Anti-amplification padding } c_hello_t; typedef struct { byte id [8]; // Command ID byte nonce [16]; // Server long-term nonce byte box [144]; // Box [S' + cookie](C'-&gt;S) } s_cookie_t; typedef struct { byte id [8]; // Command ID byte cn_client [32]; // Client short-term public key C' byte cn_cookie [96]; // Server connection cookie byte cn_nonce [8]; // Client short-term nonce byte box [112]; // Box [C + nonce + vouch](C'-&gt;S') } c_initiate_t; typedef struct { byte id [8]; // Command ID byte cn_nonce [8]; // Server short-term nonce byte box [116]; // Box [M](A'-&gt;B') (from A to B) } cs_message_t;</code></pre></div> <p>The flow is quite simple:</p> <ul> <li>Client sends a HELLO command to server</li> <li>Server responds with a COOKIE command</li> <li>Client responds with an INITIATE command</li> <li>Client can now send MESSAGE commands</li> <li>When server receives the INITIATE command, it can send messages.</li> </ul> <h2><span>Next Steps</span></h2> <p>As next step we'll implement CurveZMQ in the libzmq core and document the protocol properly as an RFC. The C implementation will act as a reference implementation for the protocol.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://hintjens.wikidot.com/blog:35</guid>
				<title>Securing ZeroMQ: the Sodium Library</title>
				<link>http://hintjens.wikidot.com/blog:35</link>
				<description>

&lt;p&gt;Marc Falzon (@falzm) pointed me to &lt;a href=&quot;https://github.com/jedisct1/libsodium/&quot;&gt;libsodium&lt;/a&gt;, aka Sodium, a repackaging of the NaCl library. The &lt;a href=&quot;https://github.com/jedisct1/libsodium/blob/master/README.markdown&quot;&gt;Sodium README&lt;/a&gt; says that it&#039;s, &amp;quot;tested on a variety of compilers and operating systems, including Windows, iOS and Android,&amp;quot; and &amp;quot;tests and benchmarks will be performed at run-time, so that the same binary package can still run everywhere.&amp;quot; This fixes the biggest problem with NaCl, which is that it optimizes at compile-time, so you can&#039;t ship it in binaries. Today I tried Sodium, and here are the results of my tests.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=99&amp;amp;amp;size=small&amp;amp;amp;timestamp=1773424598&quot; alt=&quot;pieterh&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=99)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/pieterh&quot;  &gt;pieterh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 12 Mar 2013 10:48:40 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Marc Falzon (@falzm) pointed me to <a href="https://github.com/jedisct1/libsodium/">libsodium</a>, aka Sodium, a repackaging of the NaCl library. The <a href="https://github.com/jedisct1/libsodium/blob/master/README.markdown">Sodium README</a> says that it's, &quot;tested on a variety of compilers and operating systems, including Windows, iOS and Android,&quot; and &quot;tests and benchmarks will be performed at run-time, so that the same binary package can still run everywhere.&quot; This fixes the biggest problem with NaCl, which is that it optimizes at compile-time, so you can't ship it in binaries. Today I tried Sodium, and here are the results of my tests.</p> <p>The short story is: <em>Sodium delivers</em>. This is the library I want to build ØMQ security on.</p> <p>There's so much to like about Sodium and only one downside that I'll come to. The project lives on GitHub so I forked and cloned it. It uses autotools, so builds just like all our projects do:</p> <div class="code"> <pre><code>./autogen.sh ./configure make &amp;&amp; make check &amp;&amp; make install</code></pre></div> <p>This will make it easy to integrate into FileMQ or CZMQ when the time comes. When I recall how difficult it used to be to build OpenSSL, this is gratifying. Autotools may be one of the least friendly toolsets ever but it's established a standard for C library projects that <em>just works</em>.</p> <p>So I cleaned out my NaCl installation and installed Sodium. Sodium uses the same approach as CZMQ and libzmq, which is to provide a single header file (<tt>sodium.h</tt>) for the whole library. Awesome!</p> <p>Allow me a little rant. When you make a library, please do like Sodium does, and export a single header file. Why give the user extra work with no benefit? The old technique of &quot;if you want functionality X, include header file Y&quot; was a great idea in 1970 when compilers took minutes per file, but is pathological in 2013.</p> <p>When I include <tt>czmq.h</tt> in a program, that pulls in several dozens of the commonly-used system header files as well as the whole CZMQ interface. It adds about 0.1 seconds to a compilation. Even in 1990 when this trick added 2-3 seconds, this was a good trade-off because it gave me simpler, more consistent code.</p> <p><em>It's very poor practice to start a C source file with a bunch of includes.</em> Libzmq does this and it's been a source of error and confusion. &quot;Oh yes, you have to include <tt>winsock.h</tt> but <em>after</em> that other file, otherwise you get a bad definition for the maximum sockets.&quot; Bleh. Create a project header file that sets-up the whole compile environment for you and then include that in each source.</p> <p>And export your API as one header file, please. &lt;/rant&gt;</p> <p>So here's a minimal Sodium example:</p> <div class="code"> <pre><code>#include &lt;sodium.h&gt; int main (void) { unsigned char public_key [crypto_box_PUBLICKEYBYTES]; unsigned char secret_key [crypto_box_SECRETKEYBYTES]; crypto_box_keypair (public_key, secret_key); return 0; }</code></pre></div> <p>Here's the next thing I love about Sodium: <em>it is 100% compatible with the NaCl API.</em> Not 80%, or 99%, but literally one hundred percent. It's hard to express the joy this gave me as a developer. NaCl's API is one of those &quot;love at first sight&quot; things. This is the gold standard for everyone building APIs: stick to the contracts, resist the temptation to screw over your users in the name of &quot;doing it better this time&quot;. Try designing the API right the first time around, maybe?</p> <p>Now, language bindings. Sodium reports two bindings, PyNaCl and RbNaCl. This means any design I make using Sodium will be easy to re-implement in the Python and Ruby bindings for libzmq (PyZMQ and rbzmq). Yay!</p> <p>It was literally 30 seconds' work to change, recompile, and retest my zcurve proof-of-concept. It helps that I use a <a href="https://gist.github.com/hintjens/5141852">helper script called &quot;c&quot;</a> that does smart things like searching /usr/local/lib for all libraries:</p> <div class="code"> <pre><code>~/work/zcurve$ c -l zcurve-poc Compiling zcurve-poc... Linking zcurve-poc... ~/work/zcurve$ ./zcurve-poc C:HELLO: OK S:COOKIE: OK C:INITIATE: (host=localhost) OK C:MESSAGE: (request=Hello) OK S:MESSAGE: (reply=World) OK -&gt; 'Hello World' test successful</code></pre></div> <p>Now, performance testing. Here's the performance I was getting from NaCl, compiled specifically for my AMD64 CPU:</p> <div class="code"> <pre><code>One-step box: Encryptions: 6400/second Decryptions: 6400/second Two-step box: Encryptions: 1449300/second Decryptions: 762600/second</code></pre></div> <p>The one-step box does a hashed key exchange and then does an encryption using the resulting key. The key exchange is slow, so NaCl lets you do this in two steps: do the key exchange once, and the encryption repeatedly (using a different nonce each time). That gives the second result.</p> <p>Now here are the figures for Sodium:</p> <div class="code"> <pre><code>One-step box: Encryptions: 300/second Decryptions: 300/second Two-step box: Encryptions: 733400/second Decryptions: 488800/second</code></pre></div> <p>The lesson is clear: <em>don't use single-step encryption</em> unless you're really doing a one-off (as in the start of the CurveCP handshake). The two-step encryption is about half the speed of NaCl's optimized code. The Sodium team know that performance is a concern, and they say:</p> <blockquote> <p>Optimized implementations (including NEON optimizations) will eventually be supported, but tests and benchmarks will be performed at run-time, so that the same binary package can still run everywhere.</p> </blockquote> <p>They've gotten it right: clean packaging and portability is more important than raw performance. It'll take a few years for Sodium to replace OpenSSL as the security library of choice and by that time, there will be enough people using it to make optimizations worthwhile.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/pieterh" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=99&amp;amp;size=small&amp;amp;timestamp=1773424598" alt="pieterh" style="background-image:url(http://www.wikidot.com/userkarma.php?u=99)" /></a><a href="http://www.wikidot.com/user:info/pieterh" >pieterh</a></span></p> 
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>