Use of Gotos in C code (in RSMB)

I saw that John Donovan criticised my use of gotos in the Really Small Message Broker (RSMB) C code a little while back in his article MQTT and the language of the Internet of Things.

To quote:

And, despite some missing features, a crash bug (for which I have posted a fix), and a scary number of goto statements (i.e. more than 0), it does the job admirably.

The crash bug was due to an unimplemented feature of MQTT-SN, but let’s get onto the use of gotos.  The RSMB code is written in C, not C++.  I made that decision in 2008 when I started to implement RSMB in C++.  I thought I would use all the features of C++ to build a nicely object oriented architecture, while making the code as efficient and small as it could be.  That approach lasted all of a few hours, as I  discovered that template support in the version of gcc I had to hand was decidedly dodgy.

Nothing for it, I had to resort to standard, portable C.  On the bright side, that meant I didn’t have to contend with huge standard libraries being included in the executable.  On the down side (and this is a big downside) I had to obtain or write my own collection libraries.

As RSMB became part of WebSphere MQ for a while, under the name of Telemetry Daemon for Devices, I was required to add some features to aid bug fixing.  One of these is a stack trace (the pros and cons of that belong in a different post).  What that meant is that each function had to end with a macro:


  FUNC_EXIT;
}

In those functions where some code inside a nested loop or two found an error and needed to leave the function, I had two potential approaches (apart from restructuring the loops):

  1. have multiple returns from the function, with multiple FUNC_EXIT macros, or
  2. use a goto to the single exit point of the function.

I chose the latter, as it meant only one FUNC_EXIT call was needed, meaning less scope for forgetting to include it before any return statement. This means that each function only has one exit point, which some people prefer in any case.

The use of goto is therefore constrained to the following pattern:


int function(int parm)
{
...
   goto exit;  /* an error condition */
...
   goto exit;  /* another error condition */
...

exit:
  FUNC_EXIT;
}

It struck me recently, rather belatedly, that this is what exceptions are. So if you dislike my use of gotos, please consider them to be exceptions instead.

With the right sort of macros, maybe I could even make them look like exceptions



#define raise(label) goto label;

#define handle(label) label:

but I think that would be wilfully obscure 🙂

Getting started with MQTT-SN in RSMB

Now that the source for RSMB with MQTT-SN is available, here is the quickest of quick starts to get going with MQTT-SN. More to come in due course.

The source is at http://git.eclipse.org/c/mosquitto/org.eclipse.mosquitto.rsmb.git/
in the rsmb directory. To build, go into rsmb/src and call “make”. That works well for Linux. You need a make from cygwin or similar to build for Windows.

This is an example configuration file for RSMB with MQTT-SN:


# will show you packets being sent and received
trace_output protocol						

# normal MQTT listener
listener 1883 INADDR_ANY	
		
# MQTT-S listener
listener 1884 INADDR_ANY mqtts					
	# optional multicast groups to listen on
	multicast_groups 224.0.18.83	
	# optional advertise packets parameters: address, interval, gateway_id			
	advertise 225.0.18.83:1883 30 33			

# MQTT-S outgoing multicast bridge (QoS -1)
connection mqtts_multicast						
	protocol mqtts_multicast  
	# only one address is used at the moment, plan is that a list can be used
	address 225.0.18.83:1883					
	topic a out
	topic abcdef out

# QoS 2 MQTT-S bridge
connection mqtts							
	protocol mqtts
	address 127.0.0.1:1885
	topic a out

At the moment predefined topics and sleeping clients aren’t implemented.

There is a Python MQTT-SN client in rsmb/src/MQTTSClient/Python – see mqtts.py, in the main section, for an example of using it.

MQTT, QoS and Persistence

Over the years, every now and again I get asked “what is the point of supporting QoS 1 or 2 in MQTT without full persistence?” I drew up this table a while back to help answer that question.

First a reminder of MQTT definitions of reliability of QoS:

  • 0 – at most once (fire and forget)
  • 1 – at least once
  • 2 – once only
Error Situation No Persistence Persistence
Communications errors: broken connection from whatever cause (intermittent signals e.g. over wireless, hardware problem, etc) All QoSs apply with any persistence (will hold to their reliability criteria). All QoSs apply with any persistence (will hold to their reliability criteria).
Power failure to remote host machine (bridge connection) All QoSs apply with any persistence (will hold to their reliability criteria). All QoSs apply with any persistence (will hold to their reliability criteria).
Power failure to local host machine All in-progress messages lost. Retained messages and subscriptions lost Shutdown persistence: all state since last restart lost.
Full persistence: full protection for all QoSs, as long as all persistence store write caching is turned off, both in the operating system and in the hardware. Otherwise, data can still be lost
Filesystem corruption All state lost All state lost.
Normal persistence will not help. Raid or other disk mirroring needed
Hard drive failure All state lost All state lost.
Normal persistence will not help. Raid or other disk mirroring needed
Complete system destruction All state lost All state lost.
Normal persistence will not help. Mirroring to another system needed
Destruction of location All state lost All state lost.
Normal persistence will not help. Mirroring to system in remote location needed
End of the world or universe All state lost All state lost.
Normal persistence will not help. Remote location needs to be on another planet or in another universe

Which Paho MQTT C API to use? (And some history)

It may not be obvious if you take a look at the Paho MQTT (http://mqtt.org) C client libraries (http://www.eclipse.org/paho/) , but my intention all along was to avoid proliferation of C APIs.

When I first started writing a C client for MQTT, around 2008, there was one other C MQTT API that I knew about – the now withdrawn IA93 (http://www-01.ibm.com/support/docview.wss?uid=swg24006525).  With all respect to the author, this had an interface which I did not want to copy.  Firstly, there were the variable length option structures, which meant that you had to copy topic strings, for instance, into their correct location in the structure before making the API call.  Secondly, there was the overly complicated method of setting up the API to operate with background threads.

IA93 did have one feature that I felt it was desirable to copy: the ability to work using no background threads.  As MQTT is intended for embedded devices, we would like the library to work in very simple environments.

My other starting point was the MQTT Java API at the time, I saw no reason why the C API should be much more difficult to use.  So I set out to create a C API that was close to the Java API, with the addition that it could be optionally run with no background threads.  This became the MQTTClient API (http://www.eclipse.org/paho/files/mqttdoc/Cclient/index.html).  The parameters are similar to the Java API – no unnecessary variable length structures.  The method I chose to indicate whether you want background threads or not is to simply make a call to MQTTClient_setCallbacks().  Asking for callbacks means that you have to have a background thread, right?

I was developing Really Small Message Broker (RSMB) around the same time, which is single threaded, using multiplexed I/O on the TCP port.  At the time, every MQTT server I knew of was multi-threaded – at least one thread for every connecting MQTT client.  I thought it would be interesting to see how far you could get with a single thread: reminding me of the techniques we had to use in the 1980s to write games on ZX81s and the like.  So, I thought reusing the same approach would be good for the C client – hence only one background thread no matter how many client objects you create (limited to whatever the ‘select’ system call will handle).

Another conscious decision was to use C rather than C++.  I started RSMB in C++, but quickly found out that compiler template support was pretty buggy at the time, so dropped back to ANSI standard C.  That was somewhat disappointing, but several years later does have the advantage of not being incompatible with Objective-C.

The final part of the story so far is the widespread use of graphical environments, or more accurately, environments where the application itself is a series of callbacks.   The ubiquitous example is the JavaScript program running in the web browser.  When the Paho MQTT JavaScript API was devised, it needed to be completely asynchronous.  The previous C API, in the mould of the Java API, had some calls which would block, to make programming easier.  We needed a totally asynchronous C API too, so I followed the model of the JavaScript API – which unfortunately meant a new interface, MQTTAsync (http://www.eclipse.org/paho/files/mqttdoc/Casync/index.html).

So, which to use when?

  1. MQTTClient, single-threaded: when you want to use only one thread for your entire application.
  2. MQTTClient, multi-threaded: when you want ease of use, aren’t bothered about some calls blocking, but still want messages to be sent and received in the background.
  3. MQTTAsync: when you want no calls to block at all.  (Messages will be sent and received on two background threads).

The MQTTAsync API happens to perform better than the MQTTClient API, but that wasn’t the rationale behind it.

Thanks to a Paho contributor, Frank Pagliughi, there is also now a C++ layer over the asynchronous C API.  His intent is to have an API which mirrors the corresponding Java one as much as possible.

Hmm, I think we’ve been here before!