Browse Source

Rid the project of setjmp()

Caleb James DeLisle 4 years ago
parent
commit
ca4be7578d
83 changed files with 1340 additions and 1054 deletions
  1. 1 1
      admin/Admin.c
  2. 40 53
      admin/angel/Core.c
  3. 95 98
      benc/serialization/json/JsonBencMessageReader.c
  4. 7 4
      benc/serialization/json/JsonBencMessageReader.h
  5. 1 1
      benc/serialization/json/test/JsonBencMessageReader_fuzz_test.c
  6. 48 49
      benc/serialization/standard/BencMessageReader.c
  7. 4 3
      benc/serialization/standard/BencMessageReader.h
  8. 1 1
      client/AdminClient.c
  9. 1 1
      client/Configurator.c
  10. 6 5
      client/cjdroute2.c
  11. 1 1
      dht/SerializationModule.c
  12. 64 0
      exception/Er.c
  13. 62 0
      exception/Er.h
  14. 114 0
      exception/Er.js
  15. 7 0
      exception/Except.h
  16. 0 63
      exception/Jmp.h
  17. 42 0
      exception/WinEr.h
  18. 4 6
      interface/ETHInterface.h
  19. 9 14
      interface/ETHInterface_admin.c
  20. 21 21
      interface/ETHInterface_darwin.c
  21. 12 13
      interface/ETHInterface_linux.c
  22. 10 11
      interface/UDPInterface.c
  23. 5 7
      interface/UDPInterface.h
  24. 14 18
      interface/UDPInterface_admin.c
  25. 5 8
      interface/tuntap/SocketInterface.c
  26. 4 4
      interface/tuntap/SocketInterface.h
  27. 10 10
      interface/tuntap/SocketWrapper.c
  28. 5 6
      interface/tuntap/SocketWrapper.h
  29. 5 6
      interface/tuntap/TUNInterface.h
  30. 10 11
      interface/tuntap/TUNInterface_darwin.c
  31. 7 8
      interface/tuntap/TUNInterface_freebsd.c
  32. 11 12
      interface/tuntap/TUNInterface_linux.c
  33. 7 8
      interface/tuntap/TUNInterface_netbsd.c
  34. 6 7
      interface/tuntap/TUNInterface_openbsd.c
  35. 7 8
      interface/tuntap/TUNInterface_sunos.c
  36. 4 5
      interface/tuntap/TUNInterface_win32.c
  37. 2 2
      interface/tuntap/test/TAPWrapper_root_test.c
  38. 2 2
      interface/tuntap/test/TUNInterface_ipv4_root_test.c
  39. 2 2
      interface/tuntap/test/TUNInterface_ipv6_root_test.c
  40. 3 3
      interface/tuntap/test/TUNInterface_ipv6_withroute_root_test.c
  41. 7 19
      interface/tuntap/test/TUNTools.c
  42. 5 1
      memory/Allocator.h
  43. 12 0
      node_build/builder.js
  44. 15 15
      tunnel/IpTunnel.c
  45. 5 5
      tunnel/RouteGen.c
  46. 3 4
      tunnel/RouteGen.h
  47. 8 12
      tunnel/RouteGen_admin.c
  48. 10 10
      util/Base10.c
  49. 2 1
      util/Base10.h
  50. 34 26
      util/Gcc.h
  51. 3 0
      util/Js.h
  52. 11 8
      util/Seccomp.c
  53. 2 2
      util/Seccomp.h
  54. 2 1
      util/Seccomp_dummy.c
  55. 26 22
      util/Security.c
  56. 8 9
      util/Security.h
  57. 46 56
      util/Security_admin.c
  58. 8 9
      util/Security_win32.c
  59. 6 7
      util/Setuid.h
  60. 29 0
      util/Setuid_dummy.c
  61. 10 9
      util/Setuid_linux.c
  62. 1 3
      util/events/Event.h
  63. 6 8
      util/events/Pipe.h
  64. 5 7
      util/events/UDPAddrIface.h
  65. 1 2
      util/events/libuv/Event.c
  66. 25 29
      util/events/libuv/Pipe.c
  67. 7 8
      util/events/libuv/PipeServer.c
  68. 3 3
      util/events/libuv/Pipe_pvt.h
  69. 6 8
      util/events/libuv/UDPAddrIface.c
  70. 23 22
      util/platform/netdev/NetDev.c
  71. 8 15
      util/platform/netdev/NetDev.h
  72. 6 8
      util/platform/netdev/NetPlatform.h
  73. 50 49
      util/platform/netdev/NetPlatform_darwin.c
  74. 26 25
      util/platform/netdev/NetPlatform_freebsd.c
  75. 71 71
      util/platform/netdev/NetPlatform_linux.c
  76. 24 23
      util/platform/netdev/NetPlatform_netbsd.c
  77. 22 22
      util/platform/netdev/NetPlatform_openbsd.c
  78. 27 27
      util/platform/netdev/NetPlatform_sunos.c
  79. 30 29
      util/platform/netdev/NetPlatform_win32.c
  80. 1 1
      util/test/Base10_test.c
  81. 1 1
      util/test/Process_test.c
  82. 2 2
      util/test/Seccomp_test.c
  83. 84 3
      wire/Message.h

+ 1 - 1
admin/Admin.c

@@ -439,7 +439,7 @@ static void handleMessage(struct Message* message,
 
     int origMessageLen = message->length;
     Dict* messageDict = NULL;
-    char* err = BencMessageReader_readNoExcept(message, alloc, &messageDict);
+    const char* err = BencMessageReader_readNoExcept(message, alloc, &messageDict);
     if (err) {
         Log_warn(admin->logger,
                  "Unparsable data from [%s] content: [%s] error: [%s]",

+ 40 - 53
admin/angel/Core.c

@@ -29,7 +29,7 @@
 #ifndef SUBNODE
 #include "dht/Pathfinder.h"
 #endif
-#include "exception/Jmp.h"
+#include "exception/Er.h"
 #include "interface/Iface.h"
 #include "util/events/UDPAddrIface.h"
 #include "interface/tuntap/TUNInterface.h"
@@ -155,10 +155,9 @@ static void sendResponse(String* error,
     Admin_sendMessage(output, txid, admin);
 }
 
-static void initSocket2(String* socketFullPath,
+static Er_DEFUN(void initSocket2(String* socketFullPath,
                           struct Context* ctx,
-                          uint8_t addressPrefix,
-                          struct Except* eh)
+                          uint8_t addressPrefix))
 {
     Log_debug(ctx->logger, "Initializing socket: %s;", socketFullPath->bytes);
 
@@ -169,23 +168,24 @@ static void initSocket2(String* socketFullPath,
     }
     ctx->tunAlloc = Allocator_child(ctx->alloc);
 
-    struct Iface* rawSocketIf = SocketInterface_new(
-        socketFullPath->bytes, ctx->base, ctx->logger, NULL, ctx->tunAlloc);
+    struct Iface* rawSocketIf = Er(SocketInterface_new(
+        socketFullPath->bytes, ctx->base, ctx->logger, ctx->tunAlloc));
     struct SocketWrapper* sw = SocketWrapper_new(ctx->tunAlloc, ctx->logger);
     Iface_plumb(&sw->externalIf, rawSocketIf);
 
     ctx->tunDevice = &sw->internalIf;
     Iface_plumb(ctx->tunDevice, &ctx->nc->tunAdapt->tunIf);
 
-    SocketWrapper_addAddress(&sw->externalIf, ctx->nc->myAddress->ip6.bytes, ctx->logger,
-                                eh, ctx->alloc);
-    SocketWrapper_setMTU(&sw->externalIf, DEFAULT_MTU, ctx->logger, eh, ctx->alloc);
+    Er(SocketWrapper_addAddress(
+        &sw->externalIf, ctx->nc->myAddress->ip6.bytes, ctx->logger, ctx->alloc));
+    Er(SocketWrapper_setMTU(&sw->externalIf, DEFAULT_MTU, ctx->logger, ctx->alloc));
+    Er_ret();
 }
 
-static void initTunnel2(String* desiredDeviceName,
+static Er_DEFUN(void initTunnel2(String* desiredDeviceName,
                         struct Context* ctx,
                         uint8_t addressPrefix,
-                        struct Except* eh)
+                        struct Allocator* errAlloc))
 {
     Log_debug(ctx->logger, "Initializing TUN device [%s]",
               (desiredDeviceName) ? desiredDeviceName->bytes : "<auto>");
@@ -199,8 +199,8 @@ static void initTunnel2(String* desiredDeviceName,
         ctx->tunDevice = NULL;
     }
     ctx->tunAlloc = Allocator_child(ctx->alloc);
-    ctx->tunDevice = TUNInterface_new(
-        desiredName, assignedTunName, 0, ctx->base, ctx->logger, eh, ctx->tunAlloc);
+    ctx->tunDevice = Er(TUNInterface_new(
+        desiredName, assignedTunName, 0, ctx->base, ctx->logger, ctx->tunAlloc));
 
     Iface_plumb(ctx->tunDevice, &ctx->nc->tunAdapt->tunIf);
 
@@ -210,17 +210,14 @@ static void initTunnel2(String* desiredDeviceName,
         Sockaddr_fromBytes(ctx->nc->myAddress->ip6.bytes, Sockaddr_AF_INET6, ctx->tunAlloc);
     myAddr->prefix = addressPrefix;
     myAddr->flags |= Sockaddr_flags_PREFIX;
-    NetDev_addAddress(assignedTunName, myAddr, ctx->logger, eh);
-    NetDev_setMTU(assignedTunName, DEFAULT_MTU, ctx->logger, eh);
+    Er(NetDev_addAddress(assignedTunName, myAddr, ctx->logger, errAlloc));
+    Er(NetDev_setMTU(assignedTunName, DEFAULT_MTU, ctx->logger, errAlloc));
+    Er_ret();
 }
 
-static void initTunFd0(
-    struct Context* ctx,
-    Dict* args,
-    String* txid,
-    struct Except* eh,
-    struct Allocator* requestAlloc)
+static void initTunfd(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
 {
+    struct Context* ctx = Identity_check((struct Context*) vcontext);
     int64_t* tunfd = Dict_getIntC(args, "tunfd");
     int64_t* tuntype = Dict_getIntC(args, "type");
     if (!tunfd || *tunfd < 0) {
@@ -232,7 +229,15 @@ static void initTunFd0(
     int type = (tuntype) ? *tuntype : TUNMessageType_guess();
 
     struct Allocator* tunAlloc = Allocator_child(ctx->alloc);
-    struct Pipe* p = Pipe_forFd(fileno, false, ctx->base, eh, ctx->logger, tunAlloc);
+    struct Er_Ret* er = NULL;
+    struct Pipe* p = Er_check(&er, Pipe_forFd(fileno, false, ctx->base, ctx->logger, tunAlloc));
+    if (er) {
+        Log_debug(ctx->logger, "Failed to create pipe [%s]", er->message);
+        String* error =
+            String_printf(requestAlloc, "Failed to configure tunnel [%s]", er->message);
+        sendResponse(error, ctx->admin, txid, requestAlloc);
+        return;
+    }
     struct Iface* iface = NULL;
     if (type == TUNMessageType_NONE) {
         struct AndroidWrapper* aw = AndroidWrapper_new(tunAlloc, ctx->logger);
@@ -255,20 +260,6 @@ static void initTunFd0(
     sendResponse(String_CONST("none"), ctx->admin, txid, requestAlloc);
 }
 
-static void initTunfd(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
-{
-    struct Context* ctx = Identity_check((struct Context*) vcontext);
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        initTunFd0(ctx, args, txid, &jmp.handler, requestAlloc);
-    } Jmp_catch {
-        Log_debug(ctx->logger, "Failed to create pipe [%s]", jmp.message);
-        String* error = String_printf(requestAlloc, "Failed to configure tunnel [%s]", jmp.message);
-        sendResponse(error, ctx->admin, txid, requestAlloc);
-        return;
-    }
-}
-
 static void stopTun(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
 {
     struct Context* ctx = Identity_check((struct Context*) vcontext);
@@ -289,13 +280,11 @@ static void stopTun(Dict* args, void* vcontext, String* txid, struct Allocator*
 static void initTunnel(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
 {
     struct Context* const ctx = Identity_check((struct Context*) vcontext);
-
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        String* desiredName = Dict_getStringC(args, "desiredTunName");
-        initTunnel2(desiredName, ctx, AddressCalc_ADDRESS_PREFIX_BITS, &jmp.handler);
-    } Jmp_catch {
-        String* error = String_printf(requestAlloc, "Failed to configure tunnel [%s]", jmp.message);
+    String* desiredName = Dict_getStringC(args, "desiredTunName");
+    struct Er_Ret* er = NULL;
+    Er_check(&er, initTunnel2(desiredName, ctx, AddressCalc_ADDRESS_PREFIX_BITS, requestAlloc));
+    if (er) {
+        String* error = String_printf(requestAlloc, "Failed to configure tunnel [%s]", er->message);
         sendResponse(error, ctx->admin, txid, requestAlloc);
         return;
     }
@@ -306,18 +295,15 @@ static void initTunnel(Dict* args, void* vcontext, String* txid, struct Allocato
 static void initSocket(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
 {
     struct Context* const ctx = Identity_check((struct Context*) vcontext);
-
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        String* socketFullPath = Dict_getStringC(args, "socketFullPath");
-        initSocket2(socketFullPath, ctx, AddressCalc_ADDRESS_PREFIX_BITS, &jmp.handler);
-    } Jmp_catch {
+    String* socketFullPath = Dict_getStringC(args, "socketFullPath");
+    struct Er_Ret* er = NULL;
+    Er_check(&er, initSocket2(socketFullPath, ctx, AddressCalc_ADDRESS_PREFIX_BITS));
+    if (er) {
         String* error = String_printf(requestAlloc, "Failed to configure socket [%s]",
-            jmp.message);
+            er->message);
         sendResponse(error, ctx->admin, txid, requestAlloc);
         return;
     }
-
     sendResponse(String_CONST("none"), ctx->admin, txid, requestAlloc);
 }
 
@@ -473,7 +459,7 @@ int Core_main(int argc, char** argv)
         InterfaceWaiter_waitForData(&clientPipe->iface.iface, eventBase, tempAlloc, eh);
     Log_debug(logger, "Finished getting pre-configuration from client");
     struct Sockaddr* addr = Sockaddr_clone(AddrIface_popAddr(preConf, eh), tempAlloc);
-    Dict* config = BencMessageReader_read(preConf, tempAlloc, eh);
+    Dict* config = Except_er(eh, BencMessageReader_read(preConf, tempAlloc));
 
     String* privateKeyHex = Dict_getStringC(config, "privateKey");
     Dict* adminConf = Dict_getDictC(config, "admin");
@@ -505,7 +491,8 @@ int Core_main(int argc, char** argv)
     }
 
     // --------------------- Bind Admin UDP --------------------- //
-    struct UDPAddrIface* udpAdmin = UDPAddrIface_new(eventBase, &bindAddr.addr, alloc, eh, logger);
+    struct UDPAddrIface* udpAdmin =
+        Except_er(eh, UDPAddrIface_new(eventBase, &bindAddr.addr, alloc, logger));
 
     // ---- Setup a muxer so we can get admin from socket or UDP ---- //
     struct AddrIfaceMuxer* muxer = AddrIfaceMuxer_new(logger, alloc);

+ 95 - 98
benc/serialization/json/JsonBencMessageReader.c

@@ -17,10 +17,9 @@
 #include "benc/List.h"
 #include "benc/Dict.h"
 #include "benc/String.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "wire/Message.h"
-#include "exception/Jmp.h"
 #include "util/Gcc.h"
 #include "util/Hex.h"
 #include "util/Base10.h"
@@ -29,7 +28,6 @@
 
 struct Context {
     struct Message* const msg;
-    struct Except* const eh;
     struct Allocator* const alloc;
     const bool lax;
     int line;
@@ -42,21 +40,21 @@ static int getColumn(struct Context* ctx)
 }
 
 #define ERROR0(ctx, message) \
-    Except__throw(Gcc_SHORT_FILE, Gcc_LINE, ctx->eh,    \
+    return Er__raise(Gcc_SHORT_FILE, Gcc_LINE, ctx->alloc,    \
         "Error parsing config (line %d column %d): " message, \
         ctx->line, getColumn(ctx))
 #define ERROR(ctx, message, ...) \
-    Except__throw(Gcc_SHORT_FILE, Gcc_LINE, ctx->eh,    \
+    return Er__raise(Gcc_SHORT_FILE, Gcc_LINE, ctx->alloc,    \
         "Error parsing config (line %d column %d): " message, \
         ctx->line, getColumn(ctx), __VA_ARGS__)
 
-static uint8_t peak(struct Context* ctx)
+static Er_DEFUN(uint8_t peak(struct Context* ctx))
 {
     if (!ctx->msg->length) { ERROR0(ctx, "Out of content while reading"); }
-    return ctx->msg->bytes[0];
+    Er_ret(ctx->msg->bytes[0]);
 }
 
-static void skip(struct Context* ctx, int num)
+static Er_DEFUN(void skip(struct Context* ctx, int num))
 {
     if (num > ctx->msg->length) { ERROR0(ctx, "Out of content while reading"); }
     for (int i = 0; i < num; i++) {
@@ -65,65 +63,67 @@ static void skip(struct Context* ctx, int num)
             ctx->line++;
         }
     }
-    Message_shift(ctx->msg, -num, ctx->eh);
+    Er(Message_eshift(ctx->msg, -num));
+    Er_ret();
 }
 
-static bool assertChar(struct Context* ctx, char chr, bool lax)
+static Er_DEFUN(bool assertChar(struct Context* ctx, char chr, bool lax))
 {
-    if (peak(ctx) != chr) {
-        if (lax == true) { return false; }
-        ERROR(ctx, "Expected char [%c] but got [%c]", chr, peak(ctx));
+    char c = Er(peak(ctx));
+    if (c != chr) {
+        if (lax == true) { Er_ret(false); }
+        ERROR(ctx, "Expected char [%c] but got [%c]", chr, c);
     }
-    return true;
+    Er_ret(true);
 }
 
-static void parseComment(struct Context* ctx)
+static Er_DEFUN(void parseComment(struct Context* ctx))
 {
-    assertChar(ctx, '/', false);
-    skip(ctx, 1);
-    uint8_t secondChar = peak(ctx);
+    Er(assertChar(ctx, '/', false));
+    Er(skip(ctx, 1));
+    uint8_t secondChar = Er(peak(ctx));
     if (secondChar != '/' && secondChar != '*') { ERROR(ctx, "Unexpected char [%c]", secondChar); }
     bool lastCharSplat = false;
     for (;;) {
-        skip(ctx, 1);
-        uint8_t chr = peak(ctx);
+        Er(skip(ctx, 1));
+        uint8_t chr = Er(peak(ctx));
         if (lastCharSplat && secondChar == '*' && chr == '/') {
             // get rid of the trailing *
-            skip(ctx, 1);
+            Er(skip(ctx, 1));
         } else if (secondChar == '/' && chr == '\n') {
         } else {
             lastCharSplat = (chr == '*');
             continue;
         }
-        return;
+        Er_ret();
     }
 }
 
-static void parseWhitespaceAndComments(struct Context* ctx)
+static Er_DEFUN(void parseWhitespaceAndComments(struct Context* ctx))
 {
     for (;;) {
-        switch (peak(ctx)) {
+        switch (Er(peak(ctx))) {
             case '\n':
             case ' ':
             case '\r':
             case '\t':
-                skip(ctx, 1);
+                Er(skip(ctx, 1));
                 continue;
 
             case '/':
-                parseComment(ctx);
+                Er(parseComment(ctx));
                 continue;
 
             default: break;
         }
-        return;
+        Er_ret();
     }
     ERROR0(ctx, "Reached end of message while parsing");
 }
 
-static String* parseString(struct Context* ctx)
+static Er_DEFUN(String* parseString(struct Context* ctx))
 {
-    assertChar(ctx, '"', false);
+    Er(assertChar(ctx, '"', false));
     int line = ctx->line;
     uintptr_t beginningLastLine = ctx->beginningLastLine;
     int msgLen = ctx->msg->length;
@@ -140,16 +140,16 @@ static String* parseString(struct Context* ctx)
     // CHECKFILES_IGNORE expecting a ;
 
     for (;;) {
-        skip(ctx, 1);
-        uint8_t bchar = peak(ctx);
+        Er(skip(ctx, 1));
+        uint8_t bchar = Er(peak(ctx));
         switch (bchar) {
             case '"': {
-                skip(ctx, 1);
-                if (out) { return out; }
+                Er(skip(ctx, 1));
+                if (out) { Er_ret(out); }
                 // got the length, reset and then copy the string next cycle
                 ctx->line = line;
                 ctx->beginningLastLine = beginningLastLine;
-                Message_shift(ctx->msg, msgLen - ctx->msg->length, NULL);
+                Er(Message_eshift(ctx->msg, msgLen - ctx->msg->length));
                 out = String_newBinary(NULL, pos, ctx->alloc);
                 pos = 0;
                 continue;
@@ -159,15 +159,15 @@ static String* parseString(struct Context* ctx)
                 ERROR0(ctx, "Unterminated string");
             }
             case '\\': {
-                skip(ctx, 1);
-                uint8_t x = peak(ctx);
-                skip(ctx, 1);
+                Er(skip(ctx, 1));
+                uint8_t x = Er(peak(ctx));
+                Er(skip(ctx, 1));
                 if (x != 'x') {
                     ERROR0(ctx, "Char \\ only allowed if followed by x (as in \\xff)");
                 }
-                uint8_t high = peak(ctx);
-                skip(ctx, 1);
-                uint8_t low = peak(ctx);
+                uint8_t high = Er(peak(ctx));
+                Er(skip(ctx, 1));
+                uint8_t low = Er(peak(ctx));
                 int byte = Hex_decodeByte(high, low);
                 if (byte < 0 || (byte > 255)) { ERROR0(ctx, "Invalid hex encoding"); }
                 PUSHOUT(byte);
@@ -182,38 +182,38 @@ static String* parseString(struct Context* ctx)
     #undef PUSHOUT
 }
 
-static int64_t parseInteger(struct Context* ctx)
+static Er_DEFUN(int64_t parseInteger(struct Context* ctx))
 {
-    return Base10_read(ctx->msg, ctx->eh);
+    Er_ret( Er(Base10_read(ctx->msg)) );
 }
 
-static Object* parseGeneric(struct Context* ctx);
+static Er_DEFUN(Object* parseGeneric(struct Context* ctx));
 
-static List* parseList(struct Context* ctx)
+static Er_DEFUN(List* parseList(struct Context* ctx))
 {
-    assertChar(ctx, '[', false);
-    skip(ctx, 1);
+    Er(assertChar(ctx, '[', false));
+    Er(skip(ctx, 1));
     struct List_Item* first = NULL;
     struct List_Item* last = NULL;
     for (int i = 0; ; i++) {
         for (;;) {
-            parseWhitespaceAndComments(ctx);
+            Er(parseWhitespaceAndComments(ctx));
             // lax mode, allow ,, extra ,,, commas
-            if (!ctx->lax || peak(ctx) != ',') { break; }
-            skip(ctx, 1);
+            if (!ctx->lax || Er(peak(ctx)) != ',') { break; }
+            Er(skip(ctx, 1));
         }
-        if (peak(ctx) == ']') {
-            skip(ctx, 1);
+        if (Er(peak(ctx)) == ']') {
+            Er(skip(ctx, 1));
             List* out = Allocator_malloc(ctx->alloc, sizeof(List));
             *out = first;
-            return out;
+            Er_ret(out);
         }
-        if (i && assertChar(ctx, ',', ctx->lax)) {
-            skip(ctx, 1);
-            parseWhitespaceAndComments(ctx);
+        if (i && Er(assertChar(ctx, ',', ctx->lax))) {
+            Er(skip(ctx, 1));
+            Er(parseWhitespaceAndComments(ctx));
         }
         struct List_Item* item = Allocator_calloc(ctx->alloc, sizeof(struct List_Item), 1);
-        item->elem = parseGeneric(ctx);
+        item->elem = Er(parseGeneric(ctx));
         if (last) {
             last->next = item;
         } else {
@@ -223,36 +223,36 @@ static List* parseList(struct Context* ctx)
     }
 }
 
-static Dict* parseDict(struct Context* ctx)
+static Er_DEFUN(Dict* parseDict(struct Context* ctx))
 {
-    assertChar(ctx, '{', false);
-    skip(ctx, 1);
+    Er(assertChar(ctx, '{', false));
+    Er(skip(ctx, 1));
     struct Dict_Entry* last = NULL;
     struct Dict_Entry* first = NULL;
     for (int i = 0; ; i++) {
         for (;;) {
-            parseWhitespaceAndComments(ctx);
-            if (!ctx->lax || peak(ctx) != ',') { break; }
-            skip(ctx, 1);
+            Er(parseWhitespaceAndComments(ctx));
+            if (!ctx->lax || Er(peak(ctx)) != ',') { break; }
+            Er(skip(ctx, 1));
         }
-        if (peak(ctx) == '}') {
-            skip(ctx, 1);
+        if (Er(peak(ctx)) == '}') {
+            Er(skip(ctx, 1));
             Dict* out = Allocator_malloc(ctx->alloc, sizeof(Dict));
             *out = first;
-            return out;
+            Er_ret(out);
         }
-        if (i && assertChar(ctx, ',', ctx->lax)) {
-            skip(ctx, 1);
-            parseWhitespaceAndComments(ctx);
+        if (i && Er(assertChar(ctx, ',', ctx->lax))) {
+            Er(skip(ctx, 1));
+            Er(parseWhitespaceAndComments(ctx));
         }
         struct Dict_Entry* entry = Allocator_calloc(ctx->alloc, sizeof(struct Dict_Entry), 1);
-        entry->key = parseString(ctx);
-        parseWhitespaceAndComments(ctx);
-        if (assertChar(ctx, ':', ctx->lax)) {
-            skip(ctx, 1);
-            parseWhitespaceAndComments(ctx);
+        entry->key = Er(parseString(ctx));
+        Er(parseWhitespaceAndComments(ctx));
+        if (Er(assertChar(ctx, ':', ctx->lax))) {
+            Er(skip(ctx, 1));
+            Er(parseWhitespaceAndComments(ctx));
         }
-        entry->val = parseGeneric(ctx);
+        entry->val = Er(parseGeneric(ctx));
         if (last) {
             last->next = entry;
         } else {
@@ -262,10 +262,11 @@ static Dict* parseDict(struct Context* ctx)
     }
 }
 
-static Object* parseGeneric(struct Context* ctx)
+static Er_DEFUN(Object* parseGeneric(struct Context* ctx))
 {
     Object* out = Allocator_calloc(ctx->alloc, sizeof(Object), 1);
-    switch (peak(ctx)) {
+    uint8_t c = Er(peak(ctx));
+    switch (c) {
         case '-':
         case '0':
         case '1':
@@ -278,62 +279,58 @@ static Object* parseGeneric(struct Context* ctx)
         case '8':
         case '9': {
             out->type = Object_INTEGER;
-            out->as.number = parseInteger(ctx);
+            out->as.number = Er(parseInteger(ctx));
             break;
         }
         case '[': {
             out->type = Object_LIST;
-            out->as.list = parseList(ctx);
+            out->as.list = Er(parseList(ctx));
             break;
         }
         case '{': {
             out->type = Object_DICT;
-            out->as.dictionary = parseDict(ctx);
+            out->as.dictionary = Er(parseDict(ctx));
             break;
         }
         case '"': {
             out->type = Object_STRING;
-            out->as.string = parseString(ctx);
+            out->as.string = Er(parseString(ctx));
             break;
         }
         default:
             ERROR(ctx, "While looking for something to parse: "
-                   "expected one of - 0 1 2 3 4 5 6 7 8 9 [ { \", found [%c]", peak(ctx));
+                   "expected one of - 0 1 2 3 4 5 6 7 8 9 [ { \", found [%c]", c);
     }
-    return out;
+    Er_ret(out);
 }
 
-Dict* JsonBencMessageReader_read(
+Er_DEFUN(Dict* JsonBencMessageReader_read(
     struct Message* msg,
     struct Allocator* alloc,
-    struct Except* eh,
     bool lax
-) {
+)) {
     struct Context ctx = {
         .msg = msg,
-        .eh = eh,
         .alloc = alloc,
         .lax = lax,
         .line = 1,
         .beginningLastLine = (uintptr_t) msg->bytes
     };
-    return parseDict(&ctx);
+    Er_ret( Er(parseDict(&ctx)) );
 }
 
-char* JsonBencMessageReader_readNoExcept(
+const char* JsonBencMessageReader_readNoExcept(
     struct Message* msg,
     struct Allocator* alloc,
     Dict** outPtr,
-    bool lax
-) {
-    struct Jmp j;
-    Jmp_try(j) {
-        Dict* out = JsonBencMessageReader_read(msg, alloc, &j.handler, lax);
-        *outPtr = out;
-        return NULL;
-    } Jmp_catch {
-        String* str = String_new(j.message, alloc);
-        return str->bytes;
+    bool lax)
+{
+    struct Er_Ret* er = NULL;
+    Dict* out = Er_check(&er, JsonBencMessageReader_read(msg, alloc, lax));
+    if (er) {
+        return er->message;
     }
+    *outPtr = out;
+    return NULL;
 }
 

+ 7 - 4
benc/serialization/json/JsonBencMessageReader.h

@@ -16,7 +16,7 @@
 #define JsonBencMessageReader_H
 
 #include "benc/Dict.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "wire/Message.h"
 #include "util/Linker.h"
@@ -24,9 +24,12 @@ Linker_require("benc/serialization/json/JsonBencMessageReader.c");
 
 #include <stdbool.h>
 
-Dict* JsonBencMessageReader_read(
-    struct Message* msg, struct Allocator* alloc, struct Except* eh, bool lax);
-char* JsonBencMessageReader_readNoExcept(
+Er_DEFUN(Dict* JsonBencMessageReader_read(
+    struct Message* msg,
+    struct Allocator* alloc,
+    bool lax
+));
+const char* JsonBencMessageReader_readNoExcept(
     struct Message* msg, struct Allocator* alloc, Dict** outPtr, bool lax);
 
 #endif

+ 1 - 1
benc/serialization/json/test/JsonBencMessageReader_fuzz_test.c

@@ -21,7 +21,7 @@ void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz)
 {
     struct Allocator* alloc = (struct Allocator*) vctx;
     Dict* out = NULL;
-    char* res = JsonBencMessageReader_readNoExcept(fuzz, alloc, &out, true);
+    const char* res = JsonBencMessageReader_readNoExcept(fuzz, alloc, &out, true);
     if (res) { return; }
     res = JsonBencMessageReader_readNoExcept(fuzz, alloc, &out, false);
 }

+ 48 - 49
benc/serialization/standard/BencMessageReader.c

@@ -18,96 +18,95 @@
 #include "benc/Dict.h"
 #include "benc/List.h"
 #include "benc/serialization/standard/BencMessageReader.h"
-#include "exception/Except.h"
-#include "exception/Jmp.h"
+#include "exception/Er.h"
 #include "wire/Message.h"
 #include "util/Base10.h"
 
-static Object* readGeneric(struct Message* msg, struct Allocator* alloc, struct Except* eh);
+static Er_DEFUN(Object* readGeneric(struct Message* msg, struct Allocator* alloc));
 
-static int64_t readInt(struct Message* msg, struct Allocator* alloc, struct Except* eh)
+static Er_DEFUN(int64_t readInt(struct Message* msg, struct Allocator* alloc))
 {
-    int64_t num = Base10_read(msg, eh);
-    if (Message_pop8(msg, eh) != 'e') {
-        Except_throw(eh, "Int not terminated with 'e'");
+    int64_t num = Er(Base10_read(msg));
+    if (Er(Message_epop8(msg)) != 'e') {
+        Er_raise(msg->alloc, "Int not terminated with 'e'");
     }
-    return num;
+    Er_ret(num);
 }
 
-static String* readString(struct Message* msg, struct Allocator* alloc, struct Except* eh)
+static Er_DEFUN(String* readString(struct Message* msg, struct Allocator* alloc))
 {
-    int64_t len = Base10_read(msg, eh);
+    int64_t len = Er(Base10_read(msg));
     if (len < 0) {
-        Except_throw(eh, "Negative string length");
+        Er_raise(alloc, "Negative string length");
     }
-    if (Message_pop8(msg, eh) != ':') {
-        Except_throw(eh, "String not deliniated with a ':'");
+    if (Er(Message_epop8(msg)) != ':') {
+        Er_raise(alloc, "String not deliniated with a ':'");
     }
     if (len > msg->length) {
-        Except_throw(eh, "String too long");
+        Er_raise(alloc, "String too long");
     }
     String* str = String_newBinary(NULL, len, alloc);
-    Message_pop(msg, str->bytes, len, eh);
-    return str;
+    Er(Message_epop(msg, str->bytes, len));
+    Er_ret(str);
 }
 
-static List* readList(struct Message* msg, struct Allocator* alloc, struct Except* eh)
+static Er_DEFUN(List* readList(struct Message* msg, struct Allocator* alloc))
 {
     struct List_Item* last = NULL;
     for (;;) {
-        uint8_t chr = Message_pop8(msg, eh);
+        uint8_t chr = Er(Message_epop8(msg));
         if (chr == 'e') {
             List* out = Allocator_malloc(alloc, sizeof(List));
             *out = last;
-            return out;
+            Er_ret(out);
         }
-        Message_push8(msg, chr, eh);
+        Er(Message_epush8(msg, chr));
 
         struct List_Item* item = Allocator_malloc(alloc, sizeof(struct List_Item));
-        item->elem = readGeneric(msg, alloc, eh);
+        item->elem = Er(readGeneric(msg, alloc));
         item->next = last;
         last = item;
     }
 }
 
-static Dict* readDict(struct Message* msg, struct Allocator* alloc, struct Except* eh)
+static Er_DEFUN(Dict* readDict(struct Message* msg, struct Allocator* alloc))
 {
     struct Dict_Entry* last = NULL;
     for (;;) {
-        uint8_t chr = Message_pop8(msg, eh);
+        uint8_t chr = Er(Message_epop8(msg));
         if (chr == 'e') {
             Dict* out = Allocator_malloc(alloc, sizeof(Dict));
             *out = last;
-            return out;
+            Er_ret(out);
         }
-        Message_push8(msg, chr, eh);
+        Er(Message_epush8(msg, chr));
 
         struct Dict_Entry* entry = Allocator_malloc(alloc, sizeof(struct Dict_Entry));
-        entry->key = readString(msg, alloc, eh);
-        entry->val = readGeneric(msg, alloc, eh);
+        entry->key = Er(readString(msg, alloc));
+        entry->val = Er(readGeneric(msg, alloc));
         entry->next = last;
         last = entry;
     }
 }
 
-static Object* readGeneric(struct Message* msg, struct Allocator* alloc, struct Except* eh)
+static Er_DEFUN(Object* readGeneric(struct Message* msg, struct Allocator* alloc))
 {
-    uint8_t chr = Message_pop8(msg, eh);
+    uint8_t chr = Er(Message_epop8(msg));
     Object* out = Allocator_calloc(alloc, sizeof(Object), 1);
     switch (chr) {
         case 'l': {
             out->type = Object_LIST;
-            out->as.list = readList(msg, alloc, eh);
+            out->as.list = Er(readList(msg, alloc));
             break;
         }
         case 'd': {
             out->type = Object_DICT;
-            out->as.dictionary = readDict(msg, alloc, eh);
+            out->as.dictionary = Er(readDict(msg, alloc));
             break;
         }
         case 'i': {
             out->type = Object_INTEGER;
-            out->as.number = readInt(msg, alloc, eh);
+            out->as.number = Er(readInt(msg, alloc));
             break;
         }
         case '0':
@@ -121,32 +120,32 @@ static Object* readGeneric(struct Message* msg, struct Allocator* alloc, struct
         case '8':
         case '9': {
             out->type = Object_STRING;
-            Message_push8(msg, chr, eh);
-            out->as.string = readString(msg, alloc, eh);
+            Er(Message_epush8(msg, chr));
+            out->as.string = Er(readString(msg, alloc));
             break;
         }
-        default: Except_throw(eh, "Unexpected character in message [%c]", (char)chr);
+        default: Er_raise(alloc, "Unexpected character in message [%c]", (char)chr);
     }
-    return out;
+    Er_ret(out);
 }
 
-Dict* BencMessageReader_read(struct Message* msg, struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(Dict* BencMessageReader_read(struct Message* msg, struct Allocator* alloc))
 {
-    if (Message_pop8(msg, eh) != 'd') {
-        Except_throw(eh, "Message does not begin with a 'd' to open the dictionary");
+    if (Er(Message_epop8h(msg)) != 'd') {
+        Er_raise(alloc, "Message does not begin with a 'd' to open the dictionary");
     }
-    return readDict(msg, alloc, eh);
+    Dict* out = Er(readDict(msg, alloc));
+    Er_ret(out);
 }
 
-char* BencMessageReader_readNoExcept(struct Message* msg, struct Allocator* alloc, Dict** outPtr)
+const char* BencMessageReader_readNoExcept(
+    struct Message* msg, struct Allocator* alloc, Dict** outPtr)
 {
-    struct Jmp j;
-    Jmp_try(j) {
-        Dict* out = BencMessageReader_read(msg, alloc, &j.handler);
-        *outPtr = out;
-        return NULL;
-    } Jmp_catch {
-        String* str = String_new(j.message, alloc);
-        return str->bytes;
+    struct Er_Ret* er = NULL;
+    Dict* out = Er_check(&er, BencMessageReader_read(msg, alloc));
+    if (er) {
+        return er->message;
     }
+    *outPtr = out;
+    return NULL;
 }

+ 4 - 3
benc/serialization/standard/BencMessageReader.h

@@ -16,14 +16,15 @@
 #define BencMessageReader_H
 
 #include "benc/Dict.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "wire/Message.h"
 #include "util/Linker.h"
 Linker_require("benc/serialization/standard/BencMessageReader.c");
 
-Dict* BencMessageReader_read(struct Message* msg, struct Allocator* alloc, struct Except* eh);
+Er_DEFUN(Dict* BencMessageReader_read(struct Message* msg, struct Allocator* alloc));
 
-char* BencMessageReader_readNoExcept(struct Message* msg, struct Allocator* alloc, Dict** outPtr);
+const char* BencMessageReader_readNoExcept(
+    struct Message* msg, struct Allocator* alloc, Dict** outPtr);
 
 #endif

+ 1 - 1
client/AdminClient.c

@@ -132,7 +132,7 @@ static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* addrIface)
 
     int origLen = msg->length;
     Dict* d = NULL;
-    char* err = BencMessageReader_readNoExcept(msg, alloc, &d);
+    const char* err = BencMessageReader_readNoExcept(msg, alloc, &d);
     if (err) { return NULL; }
     Message_shift(msg, origLen, NULL);
 

+ 1 - 1
client/Configurator.c

@@ -713,7 +713,7 @@ void Configurator_config(Dict* config,
                          struct Allocator* alloc)
 {
     struct Allocator* tempAlloc = Allocator_child(alloc);
-    struct UDPAddrIface* udp = UDPAddrIface_new(eventBase, NULL, alloc, NULL, logger);
+    struct UDPAddrIface* udp = Er_assert(UDPAddrIface_new(eventBase, NULL, alloc, logger));
     struct AdminClient* client =
         AdminClient_new(&udp->generic, sockAddr, adminPassword, eventBase, logger, tempAlloc);
 

+ 6 - 5
client/cjdroute2.c

@@ -508,7 +508,7 @@ static void checkRunningInstance(struct Allocator* allocator,
                      addr->bytes);
     }
 
-    struct UDPAddrIface* udp = UDPAddrIface_new(base, NULL, alloc, NULL, logger);
+    struct UDPAddrIface* udp = Except_er(eh, UDPAddrIface_new(base, NULL, alloc, logger));
     struct AdminClient* adminClient =
         AdminClient_new(&udp->generic, &pingAddrStorage.addr, password, base, logger, alloc);
 
@@ -684,7 +684,7 @@ int main(int argc, char** argv)
     struct Reader* confReader = ArrayReader_new(confMsg->bytes, confMsg->length, allocator);
     Dict _config;
     Dict* config = &_config;
-    char* err = JsonBencMessageReader_readNoExcept(confMsg, allocator, &config, false);
+    const char* err = JsonBencMessageReader_readNoExcept(confMsg, allocator, &config, false);
     if (!err) {
         // If old version is specified, always use old parser so there is no possible error
         uint64_t* v = Dict_getIntC(config, "version");
@@ -780,7 +780,7 @@ int main(int argc, char** argv)
     // cycle for up to 1 minute
     int exists = 0;
     for (int i = 0; i < 2 * 10 * 60; i++) {
-        if (Pipe_exists(pipePath->bytes, eh)) {
+        if (Except_er(eh, Pipe_exists(pipePath->bytes, allocator))) {
             exists = 1;
             break;
         }
@@ -794,7 +794,8 @@ int main(int argc, char** argv)
     }
 
     // --------------------- Connect to socket ------------------------- //
-    struct Pipe* corePipe = Pipe_named(pipePath->bytes, eventBase, eh, logger, allocator);
+    struct Pipe* corePipe =
+        Except_er(eh, Pipe_named(pipePath->bytes, eventBase, logger, allocator));
 
     // --------------------- Pre-Configure Core ------------------------- //
     Dict* preConf = Dict_new(allocator);
@@ -818,7 +819,7 @@ int main(int argc, char** argv)
 
     struct Message* fromCoreMsg =
         InterfaceWaiter_waitForData(&corePipe->iface, eventBase, allocator, eh);
-    Dict* responseFromCore = BencMessageReader_read(fromCoreMsg, allocator, eh);
+    Dict* responseFromCore = Except_er(eh, BencMessageReader_read(fromCoreMsg, allocator));
 
     // --------------------- Close the Core Pipe --------------------- //
     Allocator_free(corePipeAlloc);

+ 1 - 1
dht/SerializationModule.c

@@ -100,7 +100,7 @@ static int handleIncoming(struct DHTMessage* message,
                           void* vcontext)
 {
     struct SerializationModule_context* context = vcontext;
-    char* err =
+    const char* err =
         BencMessageReader_readNoExcept(message->binMessage, message->allocator, &message->asDict);
     if (err) {
         Log_info(context->logger, "Failed to parse message [%s]", err);

+ 64 - 0
exception/Er.c

@@ -0,0 +1,64 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#define _POSIX_C_SOURCE 200112L
+
+#include "exception/Er.h"
+#include "util/CString.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+Gcc_USE_RET
+struct Er_Ret* Er__raise(char* file, int line, struct Allocator* alloc, char* format, ...)
+{
+    va_list args;
+    va_start(args, format);
+
+    if (alloc) {
+        int written = snprintf(NULL, 0, "%s:%d ", file, line);
+        Assert_true(written >= 0);
+
+        va_list argsCopy;
+        va_copy(argsCopy, args);
+        int written2 = vsnprintf(NULL, 0, format, argsCopy);
+        Assert_true(written2 >= 0);
+        va_end(argsCopy);
+
+        int len = written + written2 + 1;
+
+        char* buf = Allocator_calloc(alloc, len, 1);
+
+        snprintf(buf, len, "%s:%d ", file, line);
+        vsnprintf(&buf[written], len - written, format, args);
+        struct Er_Ret* res = Allocator_calloc(alloc, sizeof(struct Er_Ret), 1);
+        va_end(args);
+        return res;
+    } else {
+        fprintf(stderr, "%s:%d ", file, line);
+        vfprintf(stderr, format, args);
+        fprintf(stderr, "\n");
+    }
+    abort();
+    exit(100);
+}
+
+void Er__assertFail(struct Er_Ret* er)
+{
+    if (!er) { return; }
+    fprintf(stderr, "%s\n", er->message);
+    abort();
+    exit(100);
+}

+ 62 - 0
exception/Er.h

@@ -0,0 +1,62 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef Er_H
+#define Er_H
+
+#include "memory/Allocator.h"
+#include "util/Gcc.h"
+#include "util/Js.h"
+
+#include "util/Linker.h"
+Linker_require("exception/Er.c");
+
+struct Er_Ret
+{
+    const char* message;
+};
+
+Js({ file.Er_JS = require("../exception/Er.js").create(); })
+
+#define Er_DEFUN(...) \
+    Gcc_USE_RET Js_or({ return file.Er_JS.defun(Js_Q __VA_ARGS__ Js_Q) }, __VA_ARGS__)
+
+Gcc_PRINTF(4, 5)
+Gcc_USE_RET
+struct Er_Ret* Er__raise(char* file, int line, struct Allocator* alloc, char* format, ...);
+#define Er_raise(...) \
+    do { \
+        struct Er_Ret* Er_ret = Er__raise(Gcc_SHORT_FILE, Gcc_LINE, __VA_ARGS__); \
+        Js_or({ return 'return Er_ret;' }, Er__assertFail(Er_ret)); \
+    } while (0)
+    // CHECKFILES_IGNORE missing ;
+
+#define Er(expr) Js_or({ return file.Er_JS.er(Js_Q expr Js_Q, Gcc_SHORT_FILE, Gcc_LINE); }, expr)
+
+#define Er_assert(expr) \
+    Js_or({ return file.Er_JS.assert(Js_Q expr Js_Q, Gcc_SHORT_FILE, Gcc_LINE); }, expr)
+
+#define Er_check(ret, expr) \
+    Js_or({ return file.Er_JS.check(#ret, Js_Q expr Js_Q, Gcc_SHORT_FILE, Gcc_LINE); }, expr)
+
+#define Er_ret(val) Js_or({ return file.Er_JS.ret(Js_Q val Js_Q); }, return val)
+
+static inline struct Er_Ret* Er_unwind(const char* file, int line, struct Er_Ret* ret)
+{
+    return ret;
+}
+
+void Er__assertFail(struct Er_Ret* er);
+
+#endif

+ 114 - 0
exception/Er.js

@@ -0,0 +1,114 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+const trim = (x) => {
+    if (x[0] !== ' ' || x[x.length-1] !== ' ') {
+        throw new Error("INTERNAL: Er input must begin " +
+            "with and end with a space, unrecognized [" + x + "]");
+    }
+    return x.trim();
+}
+
+const defun = (ctx, spec) => {
+    trim(spec);
+    if (spec.lastIndexOf(')') !== spec.length - 2) {
+        throw new Error("Er function spec must end " +
+            "with a ), unrecognized [" + spec + "]");
+    }
+    let c = 1;
+    let i = spec.length - 3;
+    for (; c && i >= 0; i--) {
+        c += spec[i] === ')';
+        c -= spec[i] === '(';
+    }
+    const args = spec.slice(i + 2, spec.length - 2);
+    const rettAndFunc = spec.slice(0, i + 1).trim();
+    const func = rettAndFunc.replace(/^.*\s+([a-zA-Z_][a-zA-Z0-9_]*)$/, (all, a) => a);
+    //console.log('defun: ' + rettAndFunc + ' - ' + args);
+    if (func === rettAndFunc) {
+        throw new Error("Could not parse function [" + spec + "]");
+    }
+    const rett = rettAndFunc.replace(/\s+[a-zA-Z_][a-zA-Z0-9_]*$/, '').trim();
+    ctx.activeFunction = ctx.functions[func] = { rett: rett };
+    if (rett === 'void') {
+        return 'struct Er_Ret* ' + func + '(' + args + ')';
+    } else {
+        return 'struct Er_Ret* ' + func + '(' + rett + ' *Er_returnValP, ' + args + ')';
+    }
+};
+
+const ret = (ctx, val) => {
+    val = trim(val);
+    if (ctx.activeFunction.rett === 'void') {
+        return 'return (struct Er_Ret*)0';
+    } else {
+        return '*Er_returnValP = ' + val + '; return (struct Er_Ret*)0';
+    }
+};
+
+const er = (ctx, assert, errOut, expr, file, line) => {
+    expr = trim(expr);
+    if (!/[a-zA-Z_][a-zA-Z0-9_]*\(.*\)$/.test(expr)) {
+        throw new Error("Er() expr must be in the form Er(funcName(arg1, arg2, ...)) " +
+            "in [" + expr + "]");
+    }
+    const funcName = expr.slice(0, expr.indexOf('('));
+    const f = ctx.functions[funcName];
+    if (!f) {
+        throw new Error("Er() not a defined function [" + funcName + "] in [" + expr + "]");
+    }
+    let ifret = `if (Er_ret) { return Er_unwind("${file}", ${line}, Er_ret); }`;
+    if (assert) {
+        ifret = `
+            if (Er_ret) {
+                struct Er_Ret** Er_errOut = ${errOut ? errOut : '(struct Er_Ret**)0'};
+                if (Er_errOut) {
+                    *Er_errOut = Er_unwind("${file}", ${line}, Er_ret);
+                } else {
+                    Er__assertFail(Er_unwind("${file}", ${line}, Er_ret));
+                }
+            }
+        `;
+    }
+    if (f.rett === 'void') {
+        return `do {
+            struct Er_Ret* Er_ret = ${expr};
+            ${ifret}
+        } while (0)`;
+    } else {
+        const args = expr.slice(expr.indexOf('(') + 1);
+        return `(__extension__({
+            ${f.rett} Er_returnVal;
+            __builtin_memset(&Er_returnVal, 0, sizeof(Er_returnVal));
+            struct Er_Ret* Er_ret = ${funcName}(&Er_returnVal, ${args};
+            ${ifret}
+            Er_returnVal;
+        }))`;
+    }
+};
+
+module.exports.create = () => {
+    const ctx = {
+        activeFunction: undefined,
+        functions: {},
+    };
+    return {
+        defun: (spec) => defun(ctx, spec).replace(/\n/g, ' '),
+        ret: (val) => ret(ctx, val).replace(/\n/g, ' '),
+        er: (expr, file, line) => er(ctx, false, null, expr, file, line).replace(/\n/g, ' '),
+        assert: (expr, file, line) => er(ctx, true, null, expr, file, line).replace(/\n/g, ' '),
+        check: (out, expr, file, line) => er(ctx, true, out, expr, file, line).replace(/\n/g, ' '),
+    };
+};

+ 7 - 0
exception/Except.h

@@ -15,6 +15,7 @@
 #ifndef Except_H
 #define Except_H
 
+#include "exception/Er.h"
 #include "util/Gcc.h"
 #include "util/Linker.h"
 Linker_require("exception/Except.c");
@@ -36,5 +37,11 @@ Gcc_PRINTF(4, 5)
 void Except__throw(char* file, int line, struct Except* eh, char* format, ...);
 #define Except_throw(...) Except__throw(Gcc_SHORT_FILE, Gcc_LINE, __VA_ARGS__)
 
+#define Except_er(eh, expr) (__extension__({ \
+    struct Er_Ret* ret = (struct Er_Ret*)0; \
+    __auto_type o = Er_check(&ret, expr); \
+    if (ret) { Except_throw(eh, "%s", ret->message); } \
+    o; \
+}))
 
 #endif

+ 0 - 63
exception/Jmp.h

@@ -1,63 +0,0 @@
-/* vim: set expandtab ts=4 sw=4: */
-/*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-#ifndef Jmp_H
-#define Jmp_H
-
-#include "exception/Except.h"
-#include <setjmp.h>
-
-/**
- * setjmp based exception handler.
- *
- * struct Jmp jmp;
- * Jmp_try(jmp) {
- *    Do_somethingDangerous(&jmp.handler);
- * } Jmp_catch {
- *    printf("failed %d %s", jmp.code, jmp.message);
- * }
- *
- * Provides an easy way to implement the most basic try/catch functionality.
- * the jmp structure must not be used for anything outside of the try block,
- * calling jmp.handler.exception outside of a try block is undefined behavior.
- */
-
-struct Jmp {
-    /** The exception handler which will trigger the entry into the catch block. */
-    struct Except handler;
-
-    /** The exception message if in the catch block, otherwise undefined. */
-    char* message;
-
-    /** Internal setjmp buffer. */
-    jmp_buf buf;
-};
-
-/** Internal callback, this should not be called directly. */
-Gcc_NORETURN
-static void Jmp_callback(char* message, struct Except* handler)
-{
-    struct Jmp* jmp = (struct Jmp*) handler;
-    jmp->message = message;
-    longjmp(jmp->buf, 1);
-}
-
-#define Jmp_try(jmp) \
-    jmp.handler.exception = Jmp_callback; \
-    if (!setjmp(jmp.buf))
-// CHECKFILES_IGNORE squigly bracket will be added by the caller.
-
-#define Jmp_catch else
-
-#endif

+ 42 - 0
exception/WinEr.h

@@ -0,0 +1,42 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef WinFail_H
+#define WinFail_H
+
+#include "exception/Er.h"
+#include "exception/WinFail.h"
+#include "util/Gcc.h"
+
+#define WinEr_fail(alloc, msg, status) \
+    Er_raise(alloc, "%s [%s]", msg, WinFail_strerror(status));
+
+#define WinEr_check(alloc, expr) \
+    do {                                              \
+        long status = (expr);                         \
+        if (status != ERROR_SUCCESS) {                \
+            WinEr_fail(alloc, #expr, status);         \
+        }                                             \
+    } while (0)
+// CHECKFILES_IGNORE expected ;
+
+#define WinEr_assert(eh, expr) \
+    do {                                              \
+        if (!(expr)) {                                \
+            WinEr_fail(alloc, #expr, GetLastError()); \
+        }                                             \
+    } while (0)
+// CHECKFILES_IGNORE expected ;
+
+#endif

+ 4 - 6
interface/ETHInterface.h

@@ -26,7 +26,6 @@
 #include "util/Linker.h"
 Linker_require("interface/ETHInterface_" + builder.config.systemName + ".c");
 
-Gcc_PACKED
 struct ETHInterface_Header
 {
     /** ETHInterface_CURRENT_VERSION, no communication is possible with different versions. */
@@ -40,7 +39,7 @@ struct ETHInterface_Header
 
     /** Pad to align boundry, also magic. */
     uint16_t fc00_be;
-};
+} Gcc_PACKED;
 #define ETHInterface_Header_SIZE 6
 Assert_compileTime(sizeof(struct ETHInterface_Header) == ETHInterface_Header_SIZE);
 
@@ -65,12 +64,11 @@ struct ETHInterface
     struct AddrIface generic;
 };
 
-struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
+Er_DEFUN(struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
                                       const char* bindDevice,
                                       struct Allocator* alloc,
-                                      struct Except* exHandler,
-                                      struct Log* logger);
+                                      struct Log* logger));
 
-List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh);
+Er_DEFUN(List* ETHInterface_listDevices(struct Allocator* alloc));
 
 #endif

+ 9 - 14
interface/ETHInterface_admin.c

@@ -17,7 +17,6 @@
 #include "benc/Int.h"
 #include "admin/Admin.h"
 #include "crypto/Key.h"
-#include "exception/Jmp.h"
 #include "memory/Allocator.h"
 #include "net/InterfaceController.h"
 #include "util/AddrTools.h"
@@ -87,14 +86,12 @@ static void newInterface(Dict* args, void* vcontext, String* txid, struct Alloca
     String* const bindDevice = Dict_getStringC(args, "bindDevice");
     struct Allocator* const alloc = Allocator_child(ctx->alloc);
 
-    struct ETHInterface* ethIf = NULL;
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        ethIf = ETHInterface_new(
-            ctx->eventBase, bindDevice->bytes, alloc, &jmp.handler, ctx->logger);
-    } Jmp_catch {
+    struct Er_Ret* er = NULL;
+    struct ETHInterface* ethIf =
+        Er_check(&er, ETHInterface_new(ctx->eventBase, bindDevice->bytes, alloc, ctx->logger));
+    if (er) {
         Dict* out = Dict_new(requestAlloc);
-        Dict_putStringCC(out, "error", jmp.message, requestAlloc);
+        Dict_putStringCC(out, "error", er->message, requestAlloc);
         Admin_sendMessage(out, txid, ctx->admin);
         Allocator_free(alloc);
         return;
@@ -155,13 +152,11 @@ static void beacon(Dict* args, void* vcontext, String* txid, struct Allocator* r
 static void listDevices(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
 {
     struct Context* ctx = Identity_check((struct Context*) vcontext);
-    List* devices = NULL;
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        devices = ETHInterface_listDevices(requestAlloc, &jmp.handler);
-    } Jmp_catch {
+    struct Er_Ret* er = NULL;
+    List* devices = Er_check(&er, ETHInterface_listDevices(requestAlloc));
+    if (er) {
         Dict* out = Dict_new(requestAlloc);
-        Dict_putStringCC(out, "error", jmp.message, requestAlloc);
+        Dict_putStringCC(out, "error", er->message, requestAlloc);
         Admin_sendMessage(out, txid, ctx->admin);
         return;
     }

+ 21 - 21
interface/ETHInterface_darwin.c

@@ -200,12 +200,12 @@ static void handleEvent(void* vcontext)
     }
 }
 
-List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(List* ETHInterface_listDevices(struct Allocator* alloc))
 {
     List* out = List_new(alloc);
     struct ifaddrs* ifaddr = NULL;
     if (getifaddrs(&ifaddr) || ifaddr == NULL) {
-        Except_throw(eh, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));
+        Er_raise(alloc, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));
     }
     for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
         if (!ifa->ifa_addr) {
@@ -217,7 +217,7 @@ List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh)
         }
     }
     freeifaddrs(ifaddr);
-    return out;
+    Er_ret(out);
 }
 
 static int closeSocket(struct Allocator_OnFreeJob* j)
@@ -227,44 +227,44 @@ static int closeSocket(struct Allocator_OnFreeJob* j)
     return 0;
 }
 
-static int openBPF(struct Except* eh)
+static Er_DEFUN(int openBPF(struct Allocator* alloc))
 {
     for (int retry = 0; retry < 100; retry++) {
         for (int i = 0; i < 256; i++) {
             char buf[11] = { 0 };
             snprintf(buf, 10, "/dev/bpf%i", i);
             int bpf = open(buf, O_RDWR);
-            if (bpf != -1) { return bpf; }
+            if (bpf != -1) { Er_ret(bpf); }
         }
         // sleep for 0.1 seconds
         usleep(1000 * 100);
     }
-    Except_throw(eh, "Could not find available /dev/bpf device");
+    Er_raise(alloc, "Could not find available /dev/bpf device");
 }
 
-static void macaddr(const char* ifname, uint8_t addrOut[6], struct Except* eh)
+static Er_DEFUN(void macaddr(const char* ifname, uint8_t addrOut[6], struct Allocator* alloc))
 {
     struct ifaddrs* ifa;
     if (getifaddrs(&ifa)) {
-        Except_throw(eh, "getifaddrs() -> [%s]", strerror(errno));
+        Er_raise(alloc, "getifaddrs() -> [%s]", strerror(errno));
     } else {
         for (struct ifaddrs* ifap = ifa; ifap; ifap = ifap->ifa_next) {
             if (!strcmp(ifap->ifa_name, ifname) && ifap->ifa_addr->sa_family == AF_LINK) {
                 Bits_memcpy(addrOut, LLADDR((struct sockaddr_dl*) ifap->ifa_addr), 6);
                 freeifaddrs(ifa);
-                return;
+                Er_ret();
             }
         }
     }
     freeifaddrs(ifa);
-    Except_throw(eh, "Could not find mac address for [%s]", ifname);
+    Er_raise(alloc, "Could not find mac address for [%s]", ifname);
+    Er_ret();
 }
 
-struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
+Er_DEFUN(struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
                                       const char* bindDevice,
                                       struct Allocator* alloc,
-                                      struct Except* exHandler,
-                                      struct Log* logger)
+                                      struct Log* logger))
 {
     struct ETHInterface_pvt* ctx = Allocator_calloc(alloc, sizeof(struct ETHInterface_pvt), 1);
     Identity_set(ctx);
@@ -272,25 +272,25 @@ struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
     ctx->pub.generic.alloc = alloc;
     ctx->logger = logger;
 
-    ctx->socket = openBPF(exHandler);
+    ctx->socket = Er(openBPF(alloc));
 
-    macaddr(bindDevice, ctx->myMac, exHandler);
+    Er(macaddr(bindDevice, ctx->myMac, alloc));
 
     struct ifreq ifr = { .ifr_name = { 0 } };
     CString_strcpy(ifr.ifr_name, bindDevice);
     if (ioctl(ctx->socket, BIOCSETIF, &ifr) > 0) {
-        Except_throw(exHandler, "ioctl(BIOCSETIF, [%s]) [%s]", bindDevice, strerror(errno));
+        Er_raise(alloc, "ioctl(BIOCSETIF, [%s]) [%s]", bindDevice, strerror(errno));
     }
 
     // activate immediate mode (therefore, bufLen is initially set to "1")
     int bufLen = 1;
     if (ioctl(ctx->socket, BIOCIMMEDIATE, &bufLen) == -1) {
-        Except_throw(exHandler, "ioctl(BIOCIMMEDIATE) [%s]", strerror(errno));
+        Er_raise(alloc, "ioctl(BIOCIMMEDIATE) [%s]", strerror(errno));
     }
 
     // request buffer length
     if (ioctl(ctx->socket, BIOCGBLEN, &bufLen) == -1) {
-        Except_throw(exHandler, "ioctl(BIOCGBLEN) [%s]", strerror(errno));
+        Er_raise(alloc, "ioctl(BIOCGBLEN) [%s]", strerror(errno));
     }
     Log_debug(logger, "ioctl(BIOCGBLEN) -> bufLen=%i", bufLen);
     ctx->buffer = Allocator_malloc(alloc, bufLen);
@@ -310,14 +310,14 @@ struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
         .bf_insns = cjdnsFilter,
     };
     if (ioctl(ctx->socket, BIOCSETF, &cjdnsFilterProgram) == -1) {
-        Except_throw(exHandler, "ioctl(BIOCSETF) [%s]", strerror(errno));
+        Er_raise(alloc, "ioctl(BIOCSETF) [%s]", strerror(errno));
     }
 
     Socket_makeNonBlocking(ctx->socket);
 
-    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc, exHandler);
+    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc);
 
     Allocator_onFree(alloc, closeSocket, ctx);
 
-    return &ctx->pub;
+    Er_ret(&ctx->pub);
 }

+ 12 - 13
interface/ETHInterface_linux.c

@@ -205,13 +205,13 @@ static void handleEvent(void* vcontext)
     Allocator_free(messageAlloc);
 }
 
-List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(List* ETHInterface_listDevices(struct Allocator* alloc))
 {
     List* out = List_new(alloc);
 #ifndef android
     struct ifaddrs* ifaddr = NULL;
     if (getifaddrs(&ifaddr) || ifaddr == NULL) {
-        Except_throw(eh, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));
+        Er_raise(alloc, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));
     }
     for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
         if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_PACKET) {
@@ -220,7 +220,7 @@ List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh)
     }
     freeifaddrs(ifaddr);
 #endif
-    return out;
+    Er_ret(out);
 }
 
 static int closeSocket(struct Allocator_OnFreeJob* j)
@@ -230,11 +230,10 @@ static int closeSocket(struct Allocator_OnFreeJob* j)
     return 0;
 }
 
-struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
+Er_DEFUN(struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
                                       const char* bindDevice,
                                       struct Allocator* alloc,
-                                      struct Except* exHandler,
-                                      struct Log* logger)
+                                      struct Log* logger))
 {
     struct ETHInterface_pvt* ctx = Allocator_calloc(alloc, sizeof(struct ETHInterface_pvt), 1);
     Identity_set(ctx);
@@ -246,7 +245,7 @@ struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
 
     ctx->socket = socket(AF_PACKET, SOCK_DGRAM, Ethernet_TYPE_CJDNS);
     if (ctx->socket == -1) {
-        Except_throw(exHandler, "call to socket() failed. [%s]", strerror(errno));
+        Er_raise(alloc, "call to socket() failed. [%s]", strerror(errno));
     }
     Allocator_onFree(alloc, closeSocket, ctx);
 
@@ -254,18 +253,18 @@ struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
     ctx->ifName = String_new(bindDevice, alloc);
 
     if (ioctl(ctx->socket, SIOCGIFINDEX, &ifr) == -1) {
-        Except_throw(exHandler, "failed to find interface index [%s]", strerror(errno));
+        Er_raise(alloc, "failed to find interface index [%s]", strerror(errno));
     }
     ctx->ifindex = ifr.ifr_ifindex;
 
     if (ioctl(ctx->socket, SIOCGIFFLAGS, &ifr) < 0) {
-        Except_throw(exHandler, "ioctl(SIOCGIFFLAGS) [%s]", strerror(errno));
+        Er_raise(alloc, "ioctl(SIOCGIFFLAGS) [%s]", strerror(errno));
     }
     if (!((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING))) {
         Log_info(logger, "Bringing up interface [%s]", ifr.ifr_name);
         ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
         if (ioctl(ctx->socket, SIOCSIFFLAGS, &ifr) < 0) {
-            Except_throw(exHandler, "ioctl(SIOCSIFFLAGS) [%s]", strerror(errno));
+            Er_raise(alloc, "ioctl(SIOCSIFFLAGS) [%s]", strerror(errno));
         }
     }
 
@@ -279,12 +278,12 @@ struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
     };
 
     if (bind(ctx->socket, (struct sockaddr*) &ctx->addrBase, sizeof(struct sockaddr_ll))) {
-        Except_throw(exHandler, "call to bind() failed [%s]", strerror(errno));
+        Er_raise(alloc, "call to bind() failed [%s]", strerror(errno));
     }
 
     Socket_makeNonBlocking(ctx->socket);
 
-    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc, exHandler);
+    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc);
 
-    return &ctx->pub;
+    Er_ret(&ctx->pub);
 }

+ 10 - 11
interface/UDPInterface.c

@@ -204,22 +204,21 @@ static Iface_DEFUN fromBcastSock(struct Message* m, struct Iface* iface)
     return Iface_next(&ctx->pub.generic.iface, m);
 }
 
-struct UDPInterface* UDPInterface_new(struct EventBase* eventBase,
+Er_DEFUN(struct UDPInterface* UDPInterface_new(struct EventBase* eventBase,
                                       struct Sockaddr* bindAddr,
                                       uint16_t beaconPort,
                                       struct Allocator* alloc,
-                                      struct Except* exHandler,
                                       struct Log* logger,
-                                      struct GlobalConfig* globalConf)
+                                      struct GlobalConfig* globalConf))
 {
     if (beaconPort && Sockaddr_getFamily(bindAddr) != Sockaddr_AF_INET) {
-        Except_throw(exHandler, "UDP broadcast only supported by ipv4.");
+        Er_raise(alloc, "UDP broadcast only supported by ipv4.");
     }
     if (beaconPort && Sockaddr_getPort(bindAddr) == beaconPort) {
-        Except_throw(exHandler, "UDP broadcast port must be different from communication port.");
+        Er_raise(alloc, "UDP broadcast port must be different from communication port.");
     }
 
-    struct UDPAddrIface* uai = UDPAddrIface_new(eventBase, bindAddr, alloc, exHandler, logger);
+    struct UDPAddrIface* uai = Er(UDPAddrIface_new(eventBase, bindAddr, alloc, logger));
 
     uint16_t commPort = Sockaddr_getPort(uai->generic.addr);
 
@@ -242,22 +241,22 @@ struct UDPInterface* UDPInterface_new(struct EventBase* eventBase,
         struct Sockaddr* bcastAddr = Sockaddr_clone(bindAddr, alloc);
         Sockaddr_setPort(bcastAddr, beaconPort);
         struct UDPAddrIface* bcast =
-            UDPAddrIface_new(eventBase, bcastAddr, alloc, exHandler, logger);
+            Er(UDPAddrIface_new(eventBase, bcastAddr, alloc, logger));
         UDPAddrIface_setBroadcast(bcast, 1);
         Iface_plumb(&bcast->generic.iface, &context->bcastSock);
         context->bcastIf = bcast;
     }
 
-    return &context->pub;
+    Er_ret(&context->pub);
 }
 
-List* UDPInterface_listDevices(struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(List* UDPInterface_listDevices(struct Allocator* alloc))
 {
     List* out = List_new(alloc);
     uv_interface_address_t* interfaces;
     int count;
     int res = uv_interface_addresses(&interfaces, &count);
-    if (res) { Except_throw(eh, "uv_interface_addresses failed [%s]", uv_strerror(-res)); }
+    if (res) { Er_raise(alloc, "uv_interface_addresses failed [%s]", uv_strerror(-res)); }
 
     for (int i = 0; i < count; i++) {
         if (interfaces[i].is_internal) { continue; }
@@ -265,7 +264,7 @@ List* UDPInterface_listDevices(struct Allocator* alloc, struct Except* eh)
         List_addString(out, String_new(interfaces[i].name, alloc), alloc);
     }
     uv_free_interface_addresses(interfaces, count);
-    return out;
+    Er_ret(out);
 }
 
 void UDPInterface_setBroadcastDevices(struct UDPInterface* udpif, List* devices)

+ 5 - 7
interface/UDPInterface.h

@@ -15,6 +15,7 @@
 #ifndef UDPInterface_H
 #define UDPInterface_H
 
+#include "exception/Er.h"
 #include "interface/addressable/AddrIface.h"
 #include "benc/List.h"
 #include "util/events/EventBase.h"
@@ -62,25 +63,22 @@ struct UDPInterface
  * @param bcastPort (optional) if specifed, another socket will be created for beacon messages
  *                  if zero then no other socket will be created.
  * @param alloc allocator which will be used to create the interface
- * @param exHandler in case setup fails
  * @param logger
  * @param globalConf for getting the name of the TUN device to avoid bcasting to it
  */
-struct UDPInterface* UDPInterface_new(struct EventBase* eventBase,
+Er_DEFUN(struct UDPInterface* UDPInterface_new(struct EventBase* eventBase,
                                       struct Sockaddr* bindAddr,
-                                      uint16_t bcastPort,
+                                      uint16_t beaconPort,
                                       struct Allocator* alloc,
-                                      struct Except* exHandler,
                                       struct Log* logger,
-                                      struct GlobalConfig* globalConf);
+                                      struct GlobalConfig* globalConf));
 
 /**
  * List all devices which can be broadcasted to, this will provide the name of the devices.
  *
  * @param alloc
- * @param eh exception in case libuv is unable to get the device list
  */
-List* UDPInterface_listDevices(struct Allocator* alloc, struct Except* eh);
+Er_DEFUN(List* UDPInterface_listDevices(struct Allocator* alloc));
 
 /**
  * Specify broadcast devices, this function accepts device names, address names and

+ 14 - 18
interface/UDPInterface_admin.c

@@ -14,7 +14,6 @@
  */
 #include "benc/Int.h"
 #include "admin/Admin.h"
-#include "exception/Jmp.h"
 #include "memory/Allocator.h"
 #include "net/InterfaceController.h"
 #include "util/events/EventBase.h"
@@ -152,22 +151,19 @@ static struct UDPInterface* setupLibuvUDP(struct Context* ctx,
                                        String* txid,
                                        struct Allocator* alloc)
 {
-    struct UDPInterface* udpIf = NULL;
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        udpIf = UDPInterface_new(
-            ctx->eventBase, addr, beaconPort, alloc, &jmp.handler, ctx->logger, ctx->globalConf);
-        if (dscp) {
-            if (UDPInterface_setDSCP(udpIf, dscp)) {
-                Log_warn(ctx->logger, "Set DSCP failed");
-            }
-        }
-    } Jmp_catch {
+    struct Er_Ret* er = NULL;
+    struct UDPInterface* udpIf = Er_check(&er, UDPInterface_new(
+        ctx->eventBase, addr, beaconPort, alloc, ctx->logger, ctx->globalConf));
+    if (er) {
         Dict* out = Dict_new(alloc);
-        Dict_putStringCC(out, "error", jmp.message, alloc);
+        Dict_putStringCC(out, "error", er->message, alloc);
         Admin_sendMessage(out, txid, ctx->admin);
         Allocator_free(alloc);
         return NULL;
+    } else if (dscp) {
+        if (UDPInterface_setDSCP(udpIf, dscp)) {
+            Log_warn(ctx->logger, "Set DSCP failed");
+        }
     }
     return udpIf;
 }
@@ -227,12 +223,12 @@ static void listDevices(Dict* args, void* vcontext, String* txid, struct Allocat
 {
     struct Context* ctx = Identity_check((struct Context*) vcontext);
     Dict* out = Dict_new(requestAlloc);
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        List* list = UDPInterface_listDevices(requestAlloc, &jmp.handler);
+    struct Er_Ret* er = NULL;
+    List* list = Er_check(&er, UDPInterface_listDevices(requestAlloc));
+    if (er) {
+        Dict_putStringCC(out, "error", er->message, requestAlloc);
+    } else {
         Dict_putListC(out, "ret", list, requestAlloc);
-    } Jmp_catch {
-        Dict_putStringCC(out, "error", jmp.message, requestAlloc);
     }
     Admin_sendMessage(out, txid, ctx->admin);
 }

+ 5 - 8
interface/tuntap/SocketInterface.c

@@ -13,20 +13,17 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "interface/tuntap/SocketInterface.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "util/events/EventBase.h"
 #include "util/events/Pipe.h"
 
-struct Iface* SocketInterface_new(const char* socketFullPath,
+Er_DEFUN(struct Iface* SocketInterface_new(const char* socketFullPath,
                                     struct EventBase* base,
                                     struct Log* logger,
-                                    struct Except* eh,
-                                    struct Allocator* alloc)
+                                    struct Allocator* alloc))
 {
     Log_info(logger, "Initializing socket: %s;", socketFullPath);
-
-    struct Pipe* p = Pipe_named(socketFullPath, base, eh, logger, alloc);
-
-    return &p->iface;
+    struct Pipe* p = Er(Pipe_named(socketFullPath, base, logger, alloc));
+    Er_ret(&p->iface);
 }

+ 4 - 4
interface/tuntap/SocketInterface.h

@@ -17,7 +17,8 @@
 
 #include "util/events/EventBase.h"
 #include "util/log/Log.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
+#include "interface/Iface.h"
 #include "memory/Allocator.h"
 #include "util/Linker.h"
 Linker_require("interface/tuntap/SocketInterface.c");
@@ -34,9 +35,8 @@ Linker_require("interface/tuntap/SocketInterface.c");
  * @param allocator a means of getting memory.
  * @return a Interface.
  */
-struct Iface* SocketInterface_new(const char* socketFullPath,
+Er_DEFUN(struct Iface* SocketInterface_new(const char* socketFullPath,
                                     struct EventBase* base,
                                     struct Log* logger,
-                                    struct Except* eh,
-                                    struct Allocator* alloc);
+                                    struct Allocator* alloc));
 #endif

+ 10 - 10
interface/tuntap/SocketWrapper.c

@@ -84,30 +84,30 @@ struct SocketWrapper* SocketWrapper_new(struct Allocator* alloc, struct Log* log
     return &context->pub;
 }
 
-void SocketWrapper_addAddress(struct Iface* rawSocketIf,
+Er_DEFUN(void SocketWrapper_addAddress(struct Iface* rawSocketIf,
                                 uint8_t* ipv6Addr,
                                 struct Log* logger,
-                                struct Except* eh,
-                                struct Allocator* alloc)
+                                struct Allocator* alloc))
 {
     size_t len = 16 /* IPv6 Address length */ + 1 /* Type prefix length */;
     struct Message* out = Message_new(0, len, alloc);
-    Message_push(out, ipv6Addr, 16, eh);
-    Message_push8(out, SocketWrapper_TYPE_CONF_ADD_IPV6_ADDRESS, eh);
+    Er(Message_epush(out, ipv6Addr, 16));
+    Er(Message_epush8(out, SocketWrapper_TYPE_CONF_ADD_IPV6_ADDRESS));
 
     Iface_send(rawSocketIf, out);
+    Er_ret();
 }
 
-void SocketWrapper_setMTU(struct Iface* rawSocketIf,
+Er_DEFUN(void SocketWrapper_setMTU(struct Iface* rawSocketIf,
                             uint32_t mtu,
                             struct Log* logger,
-                            struct Except* eh,
-                            struct Allocator* alloc)
+                            struct Allocator* alloc))
 {
     size_t len = 4 /* MTU var size */ + 1 /* Type prefix length */;
     struct Message* out = Message_new(0, len, alloc);
-    Message_push32(out, mtu, eh);
-    Message_push8(out, SocketWrapper_TYPE_CONF_SET_MTU, eh);
+    Er(Message_epush32be(out, mtu));
+    Er(Message_epush8(out, SocketWrapper_TYPE_CONF_SET_MTU));
 
     Iface_send(rawSocketIf, out);
+    Er_ret();
 }

+ 5 - 6
interface/tuntap/SocketWrapper.h

@@ -19,6 +19,7 @@
 #define SocketWrapper_TYPE_CONF_ADD_IPV6_ADDRESS 0x1
 #define SocketWrapper_TYPE_CONF_SET_MTU 0x2
 
+#include "exception/Er.h"
 #include "interface/Iface.h"
 #include "memory/Allocator.h"
 #include "util/log/Log.h"
@@ -33,15 +34,13 @@ struct SocketWrapper
 
 struct SocketWrapper* SocketWrapper_new(struct Allocator* alloc, struct Log* log);
 
-void SocketWrapper_addAddress(struct Iface* rawSocketIf,
+Er_DEFUN(void SocketWrapper_addAddress(struct Iface* rawSocketIf,
                                 uint8_t* ipv6Addr,
                                 struct Log* logger,
-                                struct Except* eh,
-                                struct Allocator* alloc);
+                                struct Allocator* alloc));
 
-void SocketWrapper_setMTU(struct Iface* rawSocketIf,
+Er_DEFUN(void SocketWrapper_setMTU(struct Iface* rawSocketIf,
                             uint32_t mtu,
                             struct Log* logger,
-                            struct Except* eh,
-                            struct Allocator* alloc);
+                            struct Allocator* alloc));
 #endif

+ 5 - 6
interface/tuntap/TUNInterface.h

@@ -15,10 +15,11 @@
 #ifndef TUNInterface_H
 #define TUNInterface_H
 
+#include "exception/Er.h"
+#include "interface/Iface.h"
+#include "memory/Allocator.h"
 #include "util/events/EventBase.h"
 #include "util/log/Log.h"
-#include "exception/Except.h"
-#include "memory/Allocator.h"
 #include "util/Linker.h"
 Linker_require("interface/tuntap/TUNInterface_" + builder.config.systemName + ".c");
 
@@ -42,15 +43,13 @@ Linker_require("interface/tuntap/TUNInterface_" + builder.config.systemName + ".
  * @param isTapMode if true, the TUN device will be initialized in TAP mode if supported.
  * @param base the libevent event base to use for listening for incoming packet events.
  * @param logger for logging messages about the tun device.
- * @param eh if this function fails, it will raise one an error.
  * @param allocator a means of getting memory.
  * @return a Interface.
  */
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc);
+                                   struct Allocator* alloc));
 #endif

+ 10 - 11
interface/tuntap/TUNInterface_darwin.c

@@ -41,15 +41,14 @@
 #define APPLE_UTUN_CONTROL "com.apple.net.utun_control"
 #define UTUN_OPT_IFNAME 2
 
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc)
+                                   struct Allocator* alloc))
 {
-    if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); }
+    if (isTapMode) { Er_raise(alloc, "tap mode not supported on this platform"); }
 
     int maxNameSize = (IFNAMSIZ < TUNInterface_IFNAMSIZ) ? IFNAMSIZ : TUNInterface_IFNAMSIZ;
     int tunUnit = 0; /* allocate dynamically by default */
@@ -58,7 +57,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
         int parsedUnit = 0;
 
         if (sscanf(interfaceName, "utun%i", &parsedUnit) != 1 || parsedUnit < 0) {
-            Except_throw(eh, "Invalid utun device %s", interfaceName);
+            Er_raise(alloc, "Invalid utun device %s", interfaceName);
         }
 
         tunUnit = parsedUnit + 1; /* device number used is unit - 1*/
@@ -70,7 +69,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
 
     int tunFd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
     if (tunFd < 0) {
-        Except_throw(eh, "socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL) [%s]", strerror(errno));
+        Er_raise(alloc, "socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL) [%s]", strerror(errno));
     }
 
     /* get the utun control id */
@@ -81,7 +80,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     if (ioctl(tunFd, CTLIOCGINFO, &info) < 0) {
         int err = errno;
         close(tunFd);
-        Except_throw(eh, "getting utun device id [%s]", strerror(err));
+        Er_raise(alloc, "getting utun device id [%s]", strerror(err));
     }
 
     /* connect the utun device */
@@ -96,7 +95,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     if (connect(tunFd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
         int err = errno;
         close(tunFd);
-        Except_throw(eh, "connecting to utun device [%s]", strerror(err));
+        Er_raise(alloc, "connecting to utun device [%s]", strerror(err));
     }
 
     char assignedIfName[TUNInterface_IFNAMSIZ];
@@ -109,12 +108,12 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     } else {
         int err = errno;
         close(tunFd);
-        Except_throw(eh, "getting utun interface name [%s]", strerror(err));
+        Er_raise(alloc, "getting utun interface name [%s]", strerror(err));
     }
 
-    struct Pipe* p = Pipe_forFd(tunFd, false, base, eh, logger, alloc);
+    struct Pipe* p = Er(Pipe_forFd(tunFd, false, base, logger, alloc));
 
     struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger);
     Iface_plumb(&p->iface, &bmtw->wireSide);
-    return &bmtw->inside;
+    Er_ret(&bmtw->inside);
 }

+ 7 - 8
interface/tuntap/TUNInterface_freebsd.c

@@ -38,17 +38,16 @@
 #include <netinet6/in6_var.h>
 #include <netinet6/nd6.h>
 
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc)
+                                   struct Allocator* alloc))
 {
     char deviceFile[TUNInterface_IFNAMSIZ];
 
-    if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); }
+    if (isTapMode) { Er_raise(alloc, "tap mode not supported on this platform"); }
 
     // We are on FreeBSD so we just need to read /dev/tunxx to create the tun interface
     if (interfaceName) {
@@ -83,7 +82,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
         } else if (ppa < 0) {
             error = "fdevname/getting number from fdevname";
         }
-        Except_throw(eh, "%s [%s]", error, strerror(err));
+        Er_raise(alloc, "%s [%s]", error, strerror(err));
     }
 
     // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
@@ -110,12 +109,12 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     if (error) {
         int err = errno;
         close(tunFd);
-        Except_throw(eh, "%s [%s]", error, strerror(err));
+        Er_raise(alloc, "%s [%s]", error, strerror(err));
     }
 
-    struct Pipe* p = Pipe_forFd(tunFd, false, base, eh, logger, alloc);
+    struct Pipe* p = Er(Pipe_forFd(tunFd, false, base, logger, alloc));
 
     struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger);
     Iface_plumb(&p->iface, &bmtw->wireSide);
-    return &bmtw->inside;
+    Er_ret(&bmtw->inside);
 }

+ 11 - 12
interface/tuntap/TUNInterface_linux.c

@@ -41,13 +41,12 @@
   #define DEVICE_PATH "/dev/net/tun"
 #endif
 
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc)
+                                   struct Allocator* alloc))
 {
     uint32_t maxNameSize = (IFNAMSIZ < TUNInterface_IFNAMSIZ) ? IFNAMSIZ : TUNInterface_IFNAMSIZ;
     Log_info(logger, "Initializing tun device [%s]", ((interfaceName) ? interfaceName : "auto"));
@@ -55,26 +54,26 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     struct ifreq ifRequest = { .ifr_flags = (isTapMode) ? IFF_TAP : IFF_TUN };
     if (interfaceName) {
         if (strlen(interfaceName) > maxNameSize) {
-            Except_throw(eh, "tunnel name too big, limit is [%d] characters", maxNameSize);
+            Er_raise(alloc, "tunnel name too big, limit is [%d] characters", maxNameSize);
         }
         CString_safeStrncpy(ifRequest.ifr_name, interfaceName, maxNameSize);
     }
-    int fileno = open(DEVICE_PATH, O_RDWR);
+    int tunFd = open(DEVICE_PATH, O_RDWR);
 
-    if (fileno < 0) {
-        Except_throw(eh, "open(\"%s\") [%s]", DEVICE_PATH, strerror(errno));
+    if (tunFd < 0) {
+        Er_raise(alloc, "open(\"%s\") [%s]", DEVICE_PATH, strerror(errno));
     }
 
-    if (ioctl(fileno, TUNSETIFF, &ifRequest) < 0) {
+    if (ioctl(tunFd, TUNSETIFF, &ifRequest) < 0) {
         int err = errno;
-        close(fileno);
-        Except_throw(eh, "ioctl(TUNSETIFF) [%s]", strerror(err));
+        close(tunFd);
+        Er_raise(alloc, "ioctl(TUNSETIFF) [%s]", strerror(err));
     }
     if (assignedInterfaceName) {
         CString_safeStrncpy(assignedInterfaceName, ifRequest.ifr_name, maxNameSize);
     }
 
-    struct Pipe* p = Pipe_forFd(fileno, false, base, eh, logger, alloc);
+    struct Pipe* p = Er(Pipe_forFd(tunFd, false, base, logger, alloc));
 
-    return &p->iface;
+    Er_ret(&p->iface);
 }

+ 7 - 8
interface/tuntap/TUNInterface_netbsd.c

@@ -39,15 +39,14 @@
 
 /* Tun Configurator for NetBSD. */
 
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc)
+                                   struct Allocator* alloc))
 {
-    if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); }
+    if (isTapMode) { Er_raise(alloc, "tap mode not supported on this platform"); }
     int err;
     char file[TUNInterface_IFNAMSIZ];
     int i;
@@ -65,7 +64,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     if (tunFd < 0 ) {
         err = errno;
         close(tunFd);
-        Except_throw(eh, "%s [%s]", "open(\"/dev/tunX\")", strerror(err));
+        Er_raise(alloc, "%s [%s]", "open(\"/dev/tunX\")", strerror(err));
     }
 /* from the NetBSD tun man page:
      TUNSIFHEAD  The argument should be a pointer to an int; a non-zero value
@@ -77,7 +76,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     if (ioctl(tunFd, TUNSIFHEAD, &i) == -1) {
         err = errno;
         close(tunFd);
-        Except_throw(eh, "%s [%s]", "ioctl(tunFd,TUNSIFHEAD,&2)", strerror(err));
+        Er_raise(alloc, "%s [%s]", "ioctl(tunFd,TUNSIFHEAD,&2)", strerror(err));
     }
     // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
     // so we'll skip the pretty names and call everything tunX
@@ -88,9 +87,9 @@ struct Iface* TUNInterface_new(const char* interfaceName,
             snprintf(assignedInterfaceName, TUNInterface_IFNAMSIZ, "tun%d", ppa);
         }
     }
-    struct Pipe* p = Pipe_forFd(tunFd, false, base, eh, logger, alloc);
+    struct Pipe* p = Er(Pipe_forFd(tunFd, false, base, logger, alloc));
 
     struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger);
     Iface_plumb(&p->iface, &bmtw->wireSide);
-    return &bmtw->inside;
+    Er_ret(&bmtw->inside);
 }

+ 6 - 7
interface/tuntap/TUNInterface_openbsd.c

@@ -39,15 +39,14 @@
 
 /* Tun Configurator for OpenBSD. */
 
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc)
+                                   struct Allocator* alloc))
 {
-    if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); }
+    if (isTapMode) { Er_raise(alloc, "tap mode not supported on this platform"); }
     int err;
     char file[TUNInterface_IFNAMSIZ];
     int ppa = -1; // to store the tunnel device index
@@ -65,7 +64,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     if (tunFd < 0 ) {
         err = errno;
         close(tunFd);
-        Except_throw(eh, "%s [%s]", "open(\"/dev/tunX\")", strerror(err));
+        Er_raise(alloc, "%s [%s]", "open(\"/dev/tunX\")", strerror(err));
     }
     // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
     // so we'll skip the pretty names and call everything tunX
@@ -76,9 +75,9 @@ struct Iface* TUNInterface_new(const char* interfaceName,
             snprintf(assignedInterfaceName, TUNInterface_IFNAMSIZ, "tun%d", ppa);
         }
     }
-    struct Pipe* p = Pipe_forFd(tunFd, false, base, eh, logger, alloc);
+    struct Pipe* p = Er(Pipe_forFd(tunFd, false, base, logger, alloc));
 
     struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger);
     Iface_plumb(&p->iface, &bmtw->wireSide);
-    return &bmtw->inside;
+    Er_ret(&bmtw->inside);
 }

+ 7 - 8
interface/tuntap/TUNInterface_sunos.c

@@ -89,16 +89,15 @@ static Iface_DEFUN incomingFromUs(struct Message* message, struct Iface* interna
     return Iface_next(&ctx->externalIf, message);
 }
 
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc)
+                                   struct Allocator* alloc))
 {
     // tap mode is not supported at all by the sunos tun driver.
-    if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); }
+    if (isTapMode) { Er_raise(alloc, "tap mode not supported on this platform"); }
 
     // Extract the number eg: 0 from tun0
     int ppa = 0;
@@ -140,7 +139,7 @@ struct Iface* TUNInterface_new(const char* interfaceName,
         } else if (tunFd2 < 0) {
             error = "open(\"/dev/tun\") (opening for plumbing interface)";
         }
-        Except_throw(eh, "%s [%s]", error, strerror(err));
+        Er_raise(alloc, "%s [%s]", error, strerror(err));
     }
 
     struct lifreq ifr = {
@@ -179,12 +178,12 @@ struct Iface* TUNInterface_new(const char* interfaceName,
         close(ipFd);
         close(tunFd2);
         close(tunFd);
-        Except_throw(eh, "%s [%s]", error, strerror(err));
+        Er_raise(alloc, "%s [%s]", error, strerror(err));
     }
 
     close(ipFd);
 
-    struct Pipe* p = Pipe_forFd(tunFd, false, base, eh, logger, alloc);
+    struct Pipe* p = Er(Pipe_forFd(tunFd, false, base, logger, alloc));
 
     struct TUNInterface_Illumos_pvt* ctx =
         Allocator_clone(alloc, (&(struct TUNInterface_Illumos_pvt) {
@@ -195,5 +194,5 @@ struct Iface* TUNInterface_new(const char* interfaceName,
     Iface_plumb(&ctx->externalIf, p);
     Identity_set(ctx);
 
-    return &ctx->generic;
+    Er_ret(&ctx->generic);
 }

+ 4 - 5
interface/tuntap/TUNInterface_win32.c

@@ -20,21 +20,20 @@
 #include "interface/tuntap/ARPServer.h"
 #include "util/CString.h"
 
-struct Iface* TUNInterface_new(const char* interfaceName,
+Er_DEFUN(struct Iface* TUNInterface_new(const char* interfaceName,
                                    char assignedInterfaceName[TUNInterface_IFNAMSIZ],
                                    int isTapMode,
                                    struct EventBase* base,
                                    struct Log* logger,
-                                   struct Except* eh,
-                                   struct Allocator* alloc)
+                                   struct Allocator* alloc))
 {
     struct TAPInterface* tap = TAPInterface_new(interfaceName, eh, logger, base, alloc);
     CString_safeStrncpy(assignedInterfaceName, tap->assignedName, TUNInterface_IFNAMSIZ);
-    if (isTapMode) { return &tap->generic; }
+    if (isTapMode) { Er_ret(&tap->generic); }
     struct TAPWrapper* tapWrapper = TAPWrapper_new(&tap->generic, logger, alloc);
     struct NDPServer* ndp =
         NDPServer_new(&tapWrapper->internal, logger, TAPWrapper_LOCAL_MAC, alloc);
     struct ARPServer* arp =
         ARPServer_new(&ndp->internal, logger, TAPWrapper_LOCAL_MAC, alloc);
-    return &arp->internal;
+    Er_ret(&arp->internal);
 }

+ 2 - 2
interface/tuntap/test/TAPWrapper_root_test.c

@@ -34,7 +34,7 @@ int main(int argc, char** argv)
     struct Sockaddr* addrB = Sockaddr_fromBytes(TUNTools_testIP6AddrB, Sockaddr_AF_INET6, alloc);
 
     char assignedIfName[TUNInterface_IFNAMSIZ];
-    struct Iface* tap = TUNInterface_new(NULL, assignedIfName, 1, base, log, NULL, alloc);
+    struct Iface* tap = Er_assert(TUNInterface_new(NULL, assignedIfName, 1, base, log, alloc));
     struct TAPWrapper* tapWrapper = TAPWrapper_new(tap, log, alloc);
 
     // Now setup the NDP server so the tun will work correctly.
@@ -43,7 +43,7 @@ int main(int argc, char** argv)
 
     addrA->flags |= Sockaddr_flags_PREFIX;
     addrA->prefix = 126;
-    NetDev_addAddress(assignedIfName, addrA, log, NULL);
+    Er_assert(NetDev_addAddress(assignedIfName, addrA, log, alloc));
 
     TUNTools_echoTest(addrA, addrB, TUNTools_genericIP6Echo, &arp->internal, base, log, alloc);
     Allocator_free(alloc);

+ 2 - 2
interface/tuntap/test/TUNInterface_ipv4_root_test.c

@@ -69,10 +69,10 @@ int main(int argc, char** argv)
     struct Sockaddr* addrB = Sockaddr_fromBytes(testAddrB, Sockaddr_AF_INET, alloc);
 
     char assignedIfName[TUNInterface_IFNAMSIZ];
-    struct Iface* tun = TUNInterface_new(NULL, assignedIfName, 0, base, logger, NULL, alloc);
+    struct Iface* tun = Er_assert(TUNInterface_new(NULL, assignedIfName, 0, base, logger, alloc));
     addrA->flags |= Sockaddr_flags_PREFIX;
     addrA->prefix = 30;
-    NetDev_addAddress(assignedIfName, addrA, logger, NULL);
+    Er_assert(NetDev_addAddress(assignedIfName, addrA, logger, alloc));
 
     TUNTools_echoTest(addrA, addrB, receiveMessageTUN, tun, base, logger, alloc);
     Allocator_free(alloc);

+ 2 - 2
interface/tuntap/test/TUNInterface_ipv6_root_test.c

@@ -36,10 +36,10 @@ int main(int argc, char** argv)
     struct Sockaddr* addrB = Sockaddr_fromBytes(TUNTools_testIP6AddrB, Sockaddr_AF_INET6, alloc);
 
     char assignedIfName[TUNInterface_IFNAMSIZ];
-    struct Iface* tun = TUNInterface_new(NULL, assignedIfName, 0, base, logger, NULL, alloc);
+    struct Iface* tun = Er_assert(TUNInterface_new(NULL, assignedIfName, 0, base, logger, alloc));
     addrA->flags |= Sockaddr_flags_PREFIX;
     addrA->prefix = 126;
-    NetDev_addAddress(assignedIfName, addrA, logger, NULL);
+    Er_assert(NetDev_addAddress(assignedIfName, addrA, logger, alloc));
 
     TUNTools_echoTest(addrA, addrB, TUNTools_genericIP6Echo, tun, base, logger, alloc);
     Allocator_free(alloc);

+ 3 - 3
interface/tuntap/test/TUNInterface_ipv6_withroute_root_test.c

@@ -36,13 +36,13 @@ int main(int argc, char** argv)
     struct Sockaddr* addrC = Sockaddr_fromBytes(TUNTools_testIP6AddrC, Sockaddr_AF_INET6, alloc);
 
     char assignedIfName[TUNInterface_IFNAMSIZ];
-    struct Iface* tun = TUNInterface_new(NULL, assignedIfName, 0, base, logger, NULL, alloc);
+    struct Iface* tun = Er_assert(TUNInterface_new(NULL, assignedIfName, 0, base, logger, alloc));
     addrA->flags |= Sockaddr_flags_PREFIX;
     addrA->prefix = 126;
-    NetDev_addAddress(assignedIfName, addrA, logger, NULL);
+    Er_assert(NetDev_addAddress(assignedIfName, addrA, logger, alloc));
     addrC->flags |= Sockaddr_flags_PREFIX;
     addrC->prefix = 125;
-    NetDev_setRoutes(assignedIfName, ((struct Sockaddr*[]) { addrC }) , 1, logger, alloc, NULL);
+    Er_assert(NetDev_setRoutes(assignedIfName, ((struct Sockaddr*[]) { addrC }), 1, logger, alloc));
 
     TUNTools_echoTest(addrA, addrC, TUNTools_genericIP6Echo, tun, base, logger, alloc);
     Allocator_free(alloc);

+ 7 - 19
interface/tuntap/test/TUNTools.c

@@ -15,7 +15,7 @@
 #include "interface/tuntap/TUNMessageType.h"
 #include "interface/tuntap/test/TUNTools.h"
 #include "util/events/UDPAddrIface.h"
-#include "exception/Jmp.h"
+#include "exception/Er.h"
 #include "util/events/Timeout.h"
 #include "wire/Ethernet.h"
 #include "wire/Headers.h"
@@ -27,21 +27,6 @@
     #include <unistd.h>
 #endif
 
-static struct AddrIface* setupUDP2(struct EventBase* base,
-                                   struct Sockaddr* bindAddr,
-                                   struct Allocator* allocator,
-                                   struct Log* logger)
-{
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        struct UDPAddrIface* ua = UDPAddrIface_new(base, bindAddr, allocator, &jmp.handler, logger);
-        return &ua->generic;
-    } Jmp_catch {
-        sleep(1);
-        return NULL;
-    }
-}
-
 static struct AddrIface* setupUDP(struct EventBase* base,
                                   struct Sockaddr* bindAddr,
                                   struct Allocator* allocator,
@@ -49,14 +34,17 @@ static struct AddrIface* setupUDP(struct EventBase* base,
 {
     // Mac OSX and BSD do not set up their TUN devices synchronously.
     // We'll just keep on trying until this works.
-    struct AddrIface* udp = NULL;
+    struct UDPAddrIface* udp = NULL;
+    struct Er_Ret* er = NULL;
     for (int i = 0; i < 20; i++) {
-        if ((udp = setupUDP2(base, bindAddr, allocator, logger))) {
+        udp = Er_check(&er, UDPAddrIface_new(base, bindAddr, allocator, logger));
+        if (udp) {
             break;
         }
+        sleep(1);
     }
     Assert_true(udp);
-    return udp;
+    return &udp->generic;
 }
 
 struct TUNTools_pvt

+ 5 - 1
memory/Allocator.h

@@ -361,7 +361,11 @@ void Allocator_snapshot(struct Allocator* alloc, int includeAllocations);
 #ifndef Allocator_Provider_CONTEXT_TYPE
     #define Allocator_Provider_CONTEXT_TYPE void
 #endif
-Gcc_ALLOC_SIZE(3)
+
+#ifndef __clang__
+    // clang unsupported on function pointers
+    Gcc_ALLOC_SIZE(3)
+#endif
 typedef void* (* Allocator_Provider)(Allocator_Provider_CONTEXT_TYPE* ctx,
                                      struct Allocator_Allocation* original,
                                      unsigned long size,

+ 12 - 0
node_build/builder.js

@@ -202,6 +202,18 @@ var execJs = function (js, builder, file, fileName, callback) {
 
     // # 74 "./wire/Message.h"
     js = js.replace(/\n#.*\n/g, '');
+
+    // Js_SQ Js_DQ
+    const qs = js.split('Js_Q');
+    if (qs.length && !(qs.length % 2)) {
+        throw new Error("Uneven number of Js_Q, content: [" + js + "]");
+    }
+    for (let i = 1; i < qs.length; i += 2) {
+        // escape nested quotes, they'll come back out in the final .i file
+        qs[i] = qs[i].replace(/\'/g, '\\u0027');
+    }
+    js = qs.join("'");
+
     var to = setTimeout(function () {
         throw new Error("Inline JS did not return after 120 seconds [" + js + "]");
     }, 120000);

+ 15 - 15
tunnel/IpTunnel.c

@@ -20,7 +20,6 @@
 #include "benc/serialization/standard/BencMessageReader.h"
 #include "crypto/AddressCalc.h"
 #include "crypto/random/Random.h"
-#include "exception/Jmp.h"
 #include "interface/tuntap/TUNMessageType.h"
 #include "memory/Allocator.h"
 #include "tunnel/IpTunnel.h"
@@ -410,7 +409,8 @@ static Iface_DEFUN requestForAddresses(Dict* request,
 }
 
 static void addAddress(char* printedAddr, uint8_t prefixLen,
-                       uint8_t allocSize, struct IpTunnel_pvt* ctx)
+                       uint8_t allocSize, struct IpTunnel_pvt* ctx,
+                       struct Allocator* tempAlloc)
 {
     String* tunName = GlobalConfig_getTunName(ctx->globalConf);
     if (!tunName) {
@@ -425,11 +425,10 @@ static void addAddress(char* printedAddr, uint8_t prefixLen,
     ss.addr.flags |= Sockaddr_flags_PREFIX;
 
     ss.addr.prefix = allocSize;
-    struct Jmp j;
-    Jmp_try(j) {
-        NetDev_addAddress(tunName->bytes, &ss.addr, ctx->logger, &j.handler);
-    } Jmp_catch {
-        Log_error(ctx->logger, "Error setting ip address on TUN [%s]", j.message);
+    struct Er_Ret* er = NULL;
+    Er_check(&er, NetDev_addAddress(tunName->bytes, &ss.addr, ctx->logger, tempAlloc));
+    if (er) {
+        Log_error(ctx->logger, "Error setting ip address on TUN [%s]", er->message);
         return;
     }
 
@@ -516,7 +515,8 @@ static Iface_DEFUN incomingAddresses(Dict* d,
         Log_info(context->logger, "Got issued address [%s/%d:%d] for connection [%d]",
                  printedAddr, conn->connectionIp4Alloc, conn->connectionIp4Prefix, conn->number);
 
-        addAddress(printedAddr, conn->connectionIp4Prefix, conn->connectionIp4Alloc, context);
+        addAddress(printedAddr,
+            conn->connectionIp4Prefix, conn->connectionIp4Alloc, context, alloc);
     }
 
     String* ip6 = Dict_getStringC(addresses, "ip6");
@@ -547,7 +547,8 @@ static Iface_DEFUN incomingAddresses(Dict* d,
         Log_info(context->logger, "Got issued address block [%s/%d:%d] for connection [%d]",
                  printedAddr, conn->connectionIp6Alloc, conn->connectionIp6Prefix, conn->number);
 
-        addAddress(printedAddr, conn->connectionIp6Prefix, conn->connectionIp6Alloc, context);
+        addAddress(printedAddr,
+            conn->connectionIp6Prefix, conn->connectionIp6Alloc, context, alloc);
     }
     if (context->rg->hasUncommittedChanges) {
         String* tunName = GlobalConfig_getTunName(context->globalConf);
@@ -555,11 +556,10 @@ static Iface_DEFUN incomingAddresses(Dict* d,
             Log_error(context->logger, "Failed to set routes because TUN interface is not setup");
             return 0;
         }
-        struct Jmp j;
-        Jmp_try(j) {
-            RouteGen_commit(context->rg, tunName->bytes, alloc,  &j.handler);
-        } Jmp_catch {
-            Log_error(context->logger, "Error setting routes for TUN [%s]", j.message);
+        struct Er_Ret* er = NULL;
+        Er_check(&er, RouteGen_commit(context->rg, tunName->bytes, alloc));
+        if (er) {
+            Log_error(context->logger, "Error setting routes for TUN [%s]", er->message);
             return 0;
         }
     }
@@ -587,7 +587,7 @@ static Iface_DEFUN incomingControlMessage(struct Message* message,
     struct Allocator* alloc = Allocator_child(message->alloc);
 
     Dict* d = NULL;
-    char* err = BencMessageReader_readNoExcept(message, alloc, &d);
+    const char* err = BencMessageReader_readNoExcept(message, alloc, &d);
     if (err) {
         Log_info(context->logger, "Failed to parse message [%s]", err);
         return 0;

+ 5 - 5
tunnel/RouteGen.c

@@ -635,10 +635,9 @@ Dict* RouteGen_getGeneratedRoutes(struct RouteGen* rg, struct Allocator* alloc)
     return getSomething(rp, alloc, p46->prefix6, p46->prefix4);
 }
 
-void RouteGen_commit(struct RouteGen* rg,
-                     const char* tunName,
-                     struct Allocator* tempAlloc,
-                     struct Except* eh)
+Er_DEFUN(void RouteGen_commit(struct RouteGen* rg,
+                              const char* tunName,
+                              struct Allocator* tempAlloc))
 {
     struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
     struct Prefix46* p46 = getGeneratedRoutes(rp, tempAlloc);
@@ -654,8 +653,9 @@ void RouteGen_commit(struct RouteGen* rg,
         prefixSet[prefixNum++] = sockaddrForPrefix6(tempAlloc, pfx6);
     }
     Assert_true(prefixNum == p46->prefix4->length + p46->prefix6->length);
-    NetDev_setRoutes(tunName, prefixSet, prefixNum, rp->log, tempAlloc, eh);
+    Er(NetDev_setRoutes(tunName, prefixSet, prefixNum, rp->log, tempAlloc));
     rp->pub.hasUncommittedChanges = false;
+    Er_ret();
 }
 
 static void setupDefaultLocalPrefixes(struct RouteGen_pvt* rp)

+ 3 - 4
tunnel/RouteGen.h

@@ -35,10 +35,9 @@ void RouteGen_addPrefix(struct RouteGen* rg, struct Sockaddr* destination);
 
 void RouteGen_addLocalPrefix(struct RouteGen* rg, struct Sockaddr* destination);
 
-void RouteGen_commit(struct RouteGen* rg,
-                     const char* tunName,
-                     struct Allocator* tempAlloc,
-                     struct Except* eh);
+Er_DEFUN(void RouteGen_commit(struct RouteGen* rg,
+                              const char* tunName,
+                              struct Allocator* tempAlloc));
 
 Dict* RouteGen_getPrefixes(struct RouteGen* rg, struct Allocator* alloc);
 

+ 8 - 12
tunnel/RouteGen_admin.c

@@ -15,7 +15,7 @@
 #include "benc/String.h"
 #include "benc/Dict.h"
 #include "benc/List.h"
-#include "exception/Jmp.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "tunnel/RouteGen.h"
 #include "admin/Admin.h"
@@ -178,18 +178,14 @@ static void commit(Dict* args,
     struct RouteGen_admin_Ctx* const ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext);
     String* const tunName = Dict_getStringC(args, "tunName");
     Dict* const ret = Dict_new(requestAlloc);
-    char* error;
-    struct Jmp j;
-    Jmp_try(j) {
-        RouteGen_commit(ctx->rg, tunName->bytes, requestAlloc, &j.handler);
-        error = "none";
-    } Jmp_catch {
-        error = j.message;
+    const char* error = "none";
+
+    struct Er_Ret* er = NULL;
+    Er_check(&er, RouteGen_commit(ctx->rg, tunName->bytes, requestAlloc));
+    if (er) {
+        error = er->message;
     }
-    Dict_putString(ret,
-                   String_new("error", requestAlloc),
-                   String_new(error, requestAlloc),
-                   requestAlloc);
+    Dict_putStringCC(ret, "error", error, requestAlloc);
     Admin_sendMessage(ret, txid, ctx->admin);
 }
 

+ 10 - 10
util/Base10.c

@@ -38,14 +38,14 @@ void Base10_write(struct Message* msg, int64_t num, struct Except* eh)
     }
 }
 
-int64_t Base10_read(struct Message* msg, struct Except* eh)
+Er_DEFUN(int64_t Base10_read(struct Message* msg))
 {
     int64_t out = 0;
     bool negative = false;
-    uint8_t chr = Message_pop8(msg, eh);
+    uint8_t chr = Er(Message_epop8(msg));
     if (chr == '-') {
         negative = true;
-        chr = Message_pop8(msg, eh);
+        chr = Er(Message_epop8(msg));
     }
     if (chr >= '0' && chr <= '9') {
         while (chr >= '0' && chr <= '9') {
@@ -53,16 +53,16 @@ int64_t Base10_read(struct Message* msg, struct Except* eh)
             out += chr - '0';
             if (msg->length == 0) {
                 if (negative) { out = -out; }
-                return out;
+                Er_ret(out);
             }
-            chr = Message_pop8(msg, eh);
+            chr = Er(Message_epop8(msg));
         }
-        Message_push8(msg, chr, eh);
+        Er(Message_epush8(msg, chr));
         if (negative) { out = -out; }
-        return out;
+        Er_ret(out);
     } else {
-        Message_push8(msg, chr, eh);
-        Except_throw(eh, "No base10 characters found");
+        Er(Message_epush8(msg, chr));
+        Er_raise(msg->alloc, "No base10 characters found");
     }
 }
 
@@ -79,6 +79,6 @@ int Base10_fromString(uint8_t* str, int64_t* numOut)
         return -1;
     }
     struct Message msg = { .length = len, .bytes = str, .capacity = len };
-    *numOut = Base10_read(&msg, NULL);
+    *numOut = Er_assert(Base10_read(&msg));
     return 0;
 }

+ 2 - 1
util/Base10.h

@@ -15,6 +15,7 @@
 #ifndef Base10_H
 #define Base10_H
 
+#include "exception/Er.h"
 #include "exception/Except.h"
 #include "wire/Message.h"
 #include "util/Linker.h"
@@ -23,7 +24,7 @@ Linker_require("util/Base10.c");
 #include <stdint.h>
 
 void Base10_write(struct Message* msg, int64_t num, struct Except* eh);
-int64_t Base10_read(struct Message* msg, struct Except* eh);
+Er_DEFUN(int64_t Base10_read(struct Message* msg));
 int Base10_fromString(uint8_t* str, int64_t* numOut);
 
 #endif

+ 34 - 26
util/Gcc.h

@@ -17,52 +17,56 @@
 
 #include "util/Js.h"
 
-#if !defined(__clang__) && \
-    defined(__GNUC__) && \
-    (__GNUC__ > 6)
+// GCC > 6
+#if defined(__GNUC__) && (__GNUC__ > 6)
 
 #define Gcc_FALLTHRU \
     __attribute__((fallthrough));
-
-#else
-#define Gcc_FALLTHRU
-
 #endif
 
-#if !defined(__clang__) && \
-    defined(__GNUC__) && \
-    (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+
+// clang OR GCC >= 4.4
+#if defined(__clang__) || (defined(__GNUC__) && \
+    (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)))
 
 #define Gcc_PRINTF( format_idx, arg_idx ) \
     __attribute__((__format__ (__printf__, format_idx, arg_idx)))
 
+#define Gcc_ALLOC_SIZE(...) \
+    __attribute__ ((alloc_size(__VA_ARGS__)))
+
+#define Gcc_USE_RET \
+    __attribute__ ((warn_unused_result))
+
+#define Gcc_PACKED \
+    __attribute__ ((packed))
+
 #define Gcc_NORETURN \
     __attribute__((__noreturn__))
+#endif
+
+
+// GCC >= 4.4
+#if !defined(__clang__) && \
+    defined(__GNUC__) && \
+    (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
 
 #define Gcc_NONNULL(...) \
     __attribute__((__nonnull__(__VA_ARGS__)))
 
 #define Gcc_PURE \
     __attribute__ ((__pure__))
+#endif
 
-#define Gcc_PACKED \
-    __attribute__ ((packed))
-
-#define Gcc_ALLOC_SIZE(...) \
-    __attribute__ ((alloc_size(__VA_ARGS__)))
-
-#define Gcc_USE_RET \
-    __attribute__ ((warn_unused_result))
 
-#elif defined(__clang__)
+// clang only
+#if defined(__clang__)
+// C11 only
+//#define Gcc_NORETURN _Noreturn
+#endif
 
-#define Gcc_NORETURN \
-    __attribute__((__noreturn__))
 
-#define Gcc_USE_RET \
-    __attribute__ ((warn_unused_result))
 
-#endif
 
 #ifndef Gcc_PRINTF
     #define Gcc_PRINTF( format_idx, arg_idx )
@@ -76,8 +80,12 @@
 #ifndef Gcc_PURE
     #define Gcc_PURE
 #endif
-#ifndef Gcc_PACKED
-    #define Gcc_PACKED
+// Missing this will lead to very wrong code
+// #ifndef Gcc_PACKED
+//     #define Gcc_PACKED
+// #endif
+#ifndef Gcc_FALLTHRU
+    #define Gcc_FALLTHRU
 #endif
 #ifndef Gcc_ALLOC_SIZE
     #define Gcc_ALLOC_SIZE(...)

+ 3 - 0
util/Js.h

@@ -15,6 +15,9 @@
 #ifndef Js_H
 #define Js_H
 
+// Js_Q is defined directly in builder.js because
+// you cannot define ' as a macro without the compiler complaining.
+
 #define Js_or(x,y) y
 
 #define Js(x)

+ 11 - 8
util/Seccomp.c

@@ -127,7 +127,7 @@ static struct sock_fprog* compile(struct Filter* input, int inputLen, struct All
 #define RET_ERRNO(x) (0x00050000u | ((x) & 0x0000ffffu))
 #define RET_SUCCESS   0x7fff0000u
 
-static struct sock_fprog* mkFilter(struct Allocator* alloc, struct Except* eh)
+static Er_DEFUN(struct sock_fprog* mkFilter(struct Allocator* alloc))
 {
     // Adding exceptions to the syscall filter:
     //
@@ -397,10 +397,11 @@ static struct sock_fprog* mkFilter(struct Allocator* alloc, struct Except* eh)
         RET(SECCOMP_RET_ALLOW),
     };
 
-    return compile(seccompFilter, sizeof(seccompFilter)/sizeof(seccompFilter[0]), alloc);
+    Er_ret(compile(seccompFilter, sizeof(seccompFilter)/sizeof(seccompFilter[0]), alloc));
 }
 
-static void installFilter(struct sock_fprog* filter, struct Log* logger, struct Except* eh)
+static Er_DEFUN(void installFilter(
+    struct sock_fprog* filter, struct Log* logger, struct Allocator* alloc))
 {
     struct sigaction sa = { .sa_sigaction = catchViolation, .sa_flags = SA_SIGINFO };
     if (sigaction(SIGSYS, &sa, NULL)) {
@@ -412,17 +413,19 @@ static void installFilter(struct sock_fprog* filter, struct Log* logger, struct
         Log_warn(logger, "prctl(PR_SET_NO_NEW_PRIVS) -> [%s]\n", strerror(errno));
     }
     if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, filter) == -1) {
-        Except_throw(eh, "prctl(PR_SET_SECCOMP) -> [%s]\n", strerror(errno));
+        Er_raise(alloc, "prctl(PR_SET_SECCOMP) -> [%s]\n", strerror(errno));
     }
+    Er_ret();
 }
 
-void Seccomp_dropPermissions(struct Allocator* tempAlloc, struct Log* logger, struct Except* eh)
+Er_DEFUN(void Seccomp_dropPermissions(struct Allocator* tempAlloc, struct Log* logger))
 {
-    struct sock_fprog* filter = mkFilter(tempAlloc, eh);
-    installFilter(filter, logger, eh);
+    struct sock_fprog* filter = Er(mkFilter(tempAlloc));
+    Er(installFilter(filter, logger, tempAlloc));
     if (!Seccomp_isWorking()) {
-        Except_throw(eh, "Seccomp filter not installed properly, Seccomp_isWorking() -> false");
+        Er_raise(tempAlloc, "Seccomp filter not installed properly, Seccomp_isWorking() -> false");
     }
+    Er_ret();
 }
 
 int Seccomp_isWorking(void)

+ 2 - 2
util/Seccomp.h

@@ -15,14 +15,14 @@
 #ifndef Seccomp_H
 #define Seccomp_H
 
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "util/log/Log.h"
 #include "util/Js.h"
 
 Js({ require("../util/Seccomp.js").detect(this.async, file, builder); })
 
-void Seccomp_dropPermissions(struct Allocator* tempAlloc, struct Log* logger, struct Except* eh);
+Er_DEFUN(void Seccomp_dropPermissions(struct Allocator* tempAlloc, struct Log* logger));
 
 int Seccomp_isWorking(void);
 

+ 2 - 1
util/Seccomp_dummy.c

@@ -16,8 +16,9 @@
 
 // This file is for machines which do not support seccomp.
 
-void Seccomp_dropPermissions(struct Allocator* tempAlloc, struct Log* logger, struct Except* eh)
+Er_DEFUN(void Seccomp_dropPermissions(struct Allocator* tempAlloc, struct Log* logger))
 {
+    Er_ret();
 }
 
 int Seccomp_isWorking()

+ 26 - 22
util/Security.c

@@ -57,17 +57,16 @@ Dict* Security_getUser(char* userName, struct Allocator* retAlloc)
     return ret;
 }
 
-void Security_setUser(int uid,
+Er_DEFUN(void Security_setUser(int uid,
                       int gid,
                       bool keepNetAdmin,
                       struct Log* logger,
-                      struct Except* eh,
-                      struct Allocator* alloc)
+                      struct Allocator* alloc))
 {
     int gidErrno = 0;
     int uidErrno = 0;
     if (keepNetAdmin) {
-        Setuid_preSetuid(alloc, eh);
+        Er(Setuid_preSetuid(alloc));
     }
     if (gid && setgid(gid)) {
         gidErrno = errno;
@@ -77,20 +76,21 @@ void Security_setUser(int uid,
         uidErrno = errno;
     }
     if (keepNetAdmin) {
-        Setuid_postSetuid(alloc, eh);
+        Er(Setuid_postSetuid(alloc));
     }
     if (uidErrno > 0) {
-        Except_throw(eh, "Failed to set UID [%s]", strerror(uidErrno));
+        Er_raise(alloc, "Failed to set UID [%s]", strerror(uidErrno));
     }
     if (uid != (int) getuid()) {
-        Except_throw(eh, "Failed to set UID but seemed to succeed");
+        Er_raise(alloc, "Failed to set UID but seemed to succeed");
     }
     if (gidErrno > 0) {
-        Except_throw(eh, "Failed to set GID [%s]", strerror(gidErrno));
+        Er_raise(alloc, "Failed to set GID [%s]", strerror(gidErrno));
     }
     if (gid != (int) getgid()) {
-        Except_throw(eh, "Failed to set GID but seemed to succeed");
+        Er_raise(alloc, "Failed to set GID but seemed to succeed");
     }
+    Er_ret();
 }
 
 static int canOpenFiles()
@@ -100,43 +100,47 @@ static int canOpenFiles()
     return file >= 0;
 }
 
-void Security_nofiles(struct Except* eh)
+Er_DEFUN(void Security_nofiles(struct Allocator* errAlloc))
 {
     #if !defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE)
         #define RLIMIT_NOFILE RLIMIT_OFILE
     #endif
 
     if (!canOpenFiles()) {
-        Except_throw(eh, "Unable to dupe stdin");
+        Er_raise(errAlloc, "Unable to dupe stdin");
     }
     if (setrlimit(RLIMIT_NOFILE, &(struct rlimit){ 0, 0 })) {
-        Except_throw(eh, "Failed to set open file limit to 0 [%s]", strerror(errno));
+        Er_raise(errAlloc, "Failed to set open file limit to 0 [%s]", strerror(errno));
     }
     if (canOpenFiles()) {
-        Except_throw(eh, "Still able to dupe stdin after setting number of files to 0!");
+        Er_raise(errAlloc, "Still able to dupe stdin after setting number of files to 0!");
     }
+    Er_ret();
 }
 
-void Security_noforks(struct Except* eh)
+Er_DEFUN(void Security_noforks(struct Allocator* errAlloc))
 {
     if (setrlimit(RLIMIT_NPROC, &(struct rlimit){ 0, 0 })) {
-        Except_throw(eh, "Failed to set fork limit to 0 [%s]", strerror(errno));
+        Er_raise(errAlloc, "Failed to set fork limit to 0 [%s]", strerror(errno));
     }
+    Er_ret();
 }
 
-void Security_chroot(char* root, struct Except* eh)
+Er_DEFUN(void Security_chroot(char* root, struct Allocator* errAlloc))
 {
     if (chdir(root)) {
-        Except_throw(eh, "chdir(%s) -> [%s]", root, strerror(errno));
+        Er_raise(errAlloc, "chdir(%s) -> [%s]", root, strerror(errno));
     }
     if (chroot(root)) {
-        Except_throw(eh, "chroot(%s) -> [%s]", root, strerror(errno));
+        Er_raise(errAlloc, "chroot(%s) -> [%s]", root, strerror(errno));
     }
+    Er_ret();
 }
 
-void Security_seccomp(struct Allocator* tempAlloc, struct Log* logger, struct Except* eh)
+Er_DEFUN(void Security_seccomp(struct Allocator* tempAlloc, struct Log* logger))
 {
-    Seccomp_dropPermissions(tempAlloc, logger, eh);
+    Er(Seccomp_dropPermissions(tempAlloc, logger));
+    Er_ret();
 }
 
 struct Security_pvt
@@ -171,7 +175,7 @@ struct Security* Security_new(struct Allocator* alloc, struct Log* log, struct E
     return &sec->pub;
 }
 
-struct Security_Permissions* Security_checkPermissions(struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(struct Security_Permissions* Security_checkPermissions(struct Allocator* alloc))
 {
     struct Security_Permissions* out =
         Allocator_calloc(alloc, sizeof(struct Security_Permissions), 1);
@@ -181,5 +185,5 @@ struct Security_Permissions* Security_checkPermissions(struct Allocator* alloc,
     out->seccompEnforcing = Seccomp_isWorking();
     out->uid = getuid();
 
-    return out;
+    Er_ret(out);
 }

+ 8 - 9
util/Security.h

@@ -17,7 +17,7 @@
 
 #include "benc/Dict.h"
 #include "memory/Allocator.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "util/log/Log.h"
 #include "util/events/EventBase.h"
 #include "util/Linker.h"
@@ -43,20 +43,19 @@ struct Security
     bool setupComplete;
 };
 
-void Security_setUser(int uid,
+Er_DEFUN(void Security_setUser(int uid,
                       int gid,
                       bool keepNetAdmin,
                       struct Log* logger,
-                      struct Except* eh,
-                      struct Allocator* alloc);
+                      struct Allocator* alloc));
 
-void Security_nofiles(struct Except* eh);
+Er_DEFUN(void Security_nofiles(struct Allocator* errAlloc));
 
-void Security_noforks(struct Except* eh);
+Er_DEFUN(void Security_noforks(struct Allocator* errAlloc));
 
-void Security_chroot(char* root, struct Except* eh);
+Er_DEFUN(void Security_chroot(char* root, struct Allocator* errAlloc));
 
-void Security_seccomp(struct Allocator* tempAlloc, struct Log* logger, struct Except* eh);
+Er_DEFUN(void Security_seccomp(struct Allocator* tempAlloc, struct Log* logger));
 
 void Security_setupComplete(struct Security* security);
 
@@ -64,6 +63,6 @@ struct Security* Security_new(struct Allocator* alloc, struct Log* log, struct E
 
 Dict* Security_getUser(char* userName, struct Allocator* retAlloc);
 
-struct Security_Permissions* Security_checkPermissions(struct Allocator* alloc, struct Except* eh);
+Er_DEFUN(struct Security_Permissions* Security_checkPermissions(struct Allocator* alloc));
 
 #endif

+ 46 - 56
util/Security_admin.c

@@ -15,8 +15,7 @@
 #include "admin/Admin.h"
 #include "benc/String.h"
 #include "benc/Dict.h"
-#include "exception/Except.h"
-#include "exception/Jmp.h"
+#include "exception/Er.h"
 #include "util/log/Log.h"
 #include "util/Security.h"
 #include "util/Security_admin.h"
@@ -29,64 +28,54 @@ struct Context
     Identity
 };
 
-static void sendError(char* errorMessage, String* txid, struct Admin* admin)
+static void sendError(const char* errorMessage, String* txid, struct Admin* admin)
 {
-    Dict error = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(errorMessage)), NULL);
+    Dict error = Dict_CONST(String_CONST("error"),
+        String_OBJ(String_CONST((char*)errorMessage)), NULL);
     Admin_sendMessage(&error, txid, admin);
 }
 
 static void setUser(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
 {
     struct Context* const ctx = Identity_check((struct Context*) vctx);
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        int64_t* user = Dict_getIntC(args, "uid");
-        int64_t* group = Dict_getIntC(args, "gid");
-        int gid = group ? (int)*group : 0;
-        int64_t* keepNetAdmin = Dict_getIntC(args, "keepNetAdmin");
-        Security_setUser(*user, gid, *keepNetAdmin, ctx->logger, &jmp.handler, requestAlloc);
-    } Jmp_catch {
-        sendError(jmp.message, txid, ctx->admin);
+    int64_t* user = Dict_getIntC(args, "uid");
+    int64_t* group = Dict_getIntC(args, "gid");
+    int gid = group ? (int)*group : 0;
+    int64_t* keepNetAdmin = Dict_getIntC(args, "keepNetAdmin");
+    struct Er_Ret* er = NULL;
+    Er_check(&er, Security_setUser(*user, gid, *keepNetAdmin, ctx->logger, requestAlloc));
+    if (er) {
+        sendError(er->message, txid, ctx->admin);
         return;
     }
     sendError("none", txid, ctx->admin);
 }
 
-static void checkPermissionsB(struct Except* eh,
-                              String* txid,
-                              struct Admin* admin,
-                              struct Allocator* requestAlloc)
+static void checkPermissions(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
 {
-    struct Security_Permissions* sp = Security_checkPermissions(requestAlloc, eh);
+    struct Context* const ctx = Identity_check((struct Context*) vctx);
+    struct Er_Ret* er = NULL;
+    struct Security_Permissions* sp = Er_check(&er, Security_checkPermissions(requestAlloc));
+    if (er) {
+        sendError(er->message, txid, ctx->admin);
+        return;
+    }
     Dict* out = Dict_new(requestAlloc);
     Dict_putIntC(out, "noOpenFiles", sp->noOpenFiles, requestAlloc);
     Dict_putIntC(out, "seccompExists", sp->seccompExists, requestAlloc);
     Dict_putIntC(out, "seccompEnforcing", sp->seccompEnforcing, requestAlloc);
     Dict_putIntC(out, "userId", sp->uid, requestAlloc);
     Dict_putStringCC(out, "error", "none", requestAlloc);
-    Admin_sendMessage(out, txid, admin);
+    Admin_sendMessage(out, txid, ctx->admin);
 }
 
-static void checkPermissions(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
-{
-    struct Context* const ctx = Identity_check((struct Context*) vctx);
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        checkPermissionsB(&jmp.handler, txid, ctx->admin, requestAlloc);
-    } Jmp_catch {
-        sendError(jmp.message, txid, ctx->admin);
-        return;
-    }
-}
-
-#define NOARG_CALL(vctx, txid, func) \
+#define NOARG_CALL(vctx, txid, func, requestAlloc) \
     do {                                                                    \
         struct Context* const ctx = Identity_check((struct Context*) vctx); \
-        struct Jmp jmp;                                                     \
-        Jmp_try(jmp) {                                                      \
-            func(&jmp.handler);                                             \
-        } Jmp_catch {                                                       \
-            sendError(jmp.message, txid, ctx->admin);                       \
+        struct Er_Ret* er = NULL;                                           \
+        Er_check(&er, func(requestAlloc));                                  \
+        if (er) {                                                           \
+            sendError(er->message, txid, ctx->admin);                       \
             return;                                                         \
         }                                                                   \
         sendError("none", txid, ctx->admin);                                \
@@ -95,23 +84,22 @@ static void checkPermissions(Dict* args, void* vctx, String* txid, struct Alloca
 
 static void nofiles(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
 {
-    NOARG_CALL(vctx, txid, Security_nofiles);
+    NOARG_CALL(vctx, txid, Security_nofiles, requestAlloc);
 }
 
 static void noforks(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
 {
-    NOARG_CALL(vctx, txid, Security_noforks);
+    NOARG_CALL(vctx, txid, Security_noforks, requestAlloc);
 }
 
 static void chroot(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
 {
     struct Context* const ctx = Identity_check((struct Context*) vctx);
-    struct Jmp jmp;
-    Jmp_try(jmp) {
-        String* root = Dict_getStringC(args, "root");
-        Security_chroot(root->bytes, &jmp.handler);
-    } Jmp_catch {
-        sendError(jmp.message, txid, ctx->admin);
+    struct Er_Ret* er = NULL;
+    String* root = Dict_getStringC(args, "root");
+    Er_check(&er, Security_chroot(root->bytes, requestAlloc));
+    if (er) {
+        sendError(er->message, txid, ctx->admin);
         return;
     }
     sendError("none", txid, ctx->admin);
@@ -120,17 +108,19 @@ static void chroot(Dict* args, void* vctx, String* txid, struct Allocator* reque
 static void seccomp(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
 {
     struct Context* const ctx = Identity_check((struct Context*) vctx);
-    struct Jmp jmp;
-    struct Except* eh = &jmp.handler;
-    Jmp_try(jmp) {
-        struct Security_Permissions* sp = Security_checkPermissions(requestAlloc, eh);
-        if (!sp->seccompEnforcing) {
-            Security_seccomp(requestAlloc, ctx->logger, eh);
-        } else {
-            sendError("seccomp is already enabled", txid, ctx->admin);
-        }
-    } Jmp_catch {
-        sendError(jmp.message, txid, ctx->admin);
+    struct Er_Ret* er = NULL;
+    struct Security_Permissions* sp = Er_check(&er, Security_checkPermissions(requestAlloc));
+    if (er) {
+        sendError(er->message, txid, ctx->admin);
+        return;
+    }
+    if (sp->seccompEnforcing) {
+        sendError("seccomp is already enabled", txid, ctx->admin);
+        return;
+    }
+    Er_check(&er, Security_seccomp(requestAlloc, ctx->logger));
+    if (er) {
+        sendError(er->message, txid, ctx->admin);
         return;
     }
     sendError("none", txid, ctx->admin);

+ 8 - 9
util/Security_win32.c

@@ -14,7 +14,7 @@
  */
 #include "benc/Dict.h"
 #include "benc/String.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "util/log/Log.h"
 #include "util/Security.h"
 #include "memory/Allocator.h"
@@ -33,28 +33,27 @@ Dict* Security_getUser(char* userName, struct Allocator* retAlloc)
     return ret;
 }
 
-void Security_setUser(int uid,
+Er_DEFUN(void Security_setUser(int uid,
                       int gid,
                       bool keepNetAdmin,
                       struct Log* logger,
-                      struct Except* eh,
-                      struct Allocator* alloc)
+                      struct Allocator* alloc))
 {
 }
 
-void Security_nofiles(struct Except* eh)
+Er_DEFUN(void Security_nofiles(struct Allocator* errAlloc))
 {
 }
 
-void Security_noforks(struct Except* eh)
+Er_DEFUN(void Security_noforks(struct Allocator* errAlloc))
 {
 }
 
-void Security_chroot(char* root, struct Except* eh)
+Er_DEFUN(void Security_chroot(char* root, struct Allocator* errAlloc))
 {
 }
 
-void Security_seccomp(struct Allocator* tempAlloc, struct Log* logger, struct Except* eh)
+Er_DEFUN(void Security_seccomp(struct Allocator* tempAlloc, struct Log* logger))
 {
 }
 
@@ -90,7 +89,7 @@ struct Security* Security_new(struct Allocator* alloc, struct Log* log, struct E
     return &sec->pub;
 }
 
-struct Security_Permissions* Security_checkPermissions(struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(struct Security_Permissions* Security_checkPermissions(struct Allocator* alloc))
 {
     struct Security_Permissions* out =
         Allocator_calloc(alloc, sizeof(struct Security_Permissions), 1);

+ 6 - 7
util/Setuid.h

@@ -20,23 +20,22 @@
 #include "util/Linker.h"
 #define Setuid_IMPL "util/Setuid_" + builder.config.systemName + ".c"
 
-void Setuid_preSetuid(struct Allocator* alloc, struct Except* eh);
-void Setuid_postSetuid(struct Allocator* alloc, struct Except* eh);
+Er_DEFUN(void Setuid_preSetuid(struct Allocator* alloc));
+Er_DEFUN(void Setuid_postSetuid(struct Allocator* alloc));
 
-<?js
+Js({
     var done = this.async();
     require("fs").exists(Setuid_IMPL, function (exists) {
         var out = "";
         if (!exists) {
-            out = "void Setuid_preSetuid(struct Allocator* alloc, struct Except* eh) { }\n" +
-                "void Setuid_postSetuid(struct Allocator* alloc, struct Except* eh) { }";
             console.log("No setuid keepNetAdmin");
+            file.links.push("util/Setuid_dummy.c");
         } else {
             file.links.push(Setuid_IMPL);
             console.log("Has setuid keepNetAdmin");
         }
-        done(out);
+        done();
     });
-?>
+})
 
 #endif

+ 29 - 0
util/Setuid_dummy.c

@@ -0,0 +1,29 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "util/Setuid.h"
+#include "memory/Allocator.h"
+#include "exception/Er.h"
+
+// This implementation does nothing
+
+Er_DEFUN(void Setuid_preSetuid(struct Allocator* alloc))
+{
+    Er_ret();
+}
+
+Er_DEFUN(void Setuid_postSetuid(struct Allocator* alloc))
+{
+    Er_ret();
+}

+ 10 - 9
util/Setuid_linux.c

@@ -16,7 +16,6 @@
 #include "memory/Allocator.h"
 #include "exception/Except.h"
 
-//#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
@@ -51,7 +50,7 @@ static inline int capGet(cap_user_header_t hdr, cap_user_data_t data)
     return capget(hdr, data);
 }
 
-void Setuid_preSetuid(struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(void Setuid_preSetuid(struct Allocator* alloc))
 {
     cap_user_header_t hdr = Allocator_calloc(alloc, sizeof(*hdr), 1);
     cap_user_data_t data = Allocator_calloc(alloc, sizeof(*data), 2);
@@ -59,22 +58,23 @@ void Setuid_preSetuid(struct Allocator* alloc, struct Except* eh)
     hdr->version = _LINUX_CAPABILITY_VERSION_3;
     hdr->pid = 0;
     if (capGet(hdr, data)) {
-        Except_throw(eh, "Error getting capabilities: [errno:%d (%s)]", errno, strerror(errno));
+        Er_raise(alloc, "Error getting capabilities: [errno:%d (%s)]", errno, strerror(errno));
     }
 
     data->permitted &= PERMITTED_MASK | CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID);
     data->effective = data->permitted;
     data->inheritable = 0;
     if (capSet(hdr, data)) {
-        Except_throw(eh, "Error setting capabilities: [errno:%d (%s)]", errno, strerror(errno));
+        Er_raise(alloc, "Error setting capabilities: [errno:%d (%s)]", errno, strerror(errno));
     }
 
     if (prctl(PR_SET_KEEPCAPS, 1)) {
-        Except_throw(eh, "Error keeping capabilities: [errno:%d (%s)]", errno, strerror(errno));
+        Er_raise(alloc, "Error keeping capabilities: [errno:%d (%s)]", errno, strerror(errno));
     }
+    Er_ret();
 }
 
-void Setuid_postSetuid(struct Allocator* alloc, struct Except* eh)
+Er_DEFUN(void Setuid_postSetuid(struct Allocator* alloc))
 {
     cap_user_header_t hdr = Allocator_calloc(alloc, sizeof(*hdr), 1);
     cap_user_data_t data = Allocator_calloc(alloc, sizeof(*data), 2);
@@ -82,7 +82,7 @@ void Setuid_postSetuid(struct Allocator* alloc, struct Except* eh)
     hdr->version = _LINUX_CAPABILITY_VERSION_3;
     hdr->pid = 0;
     if (capGet(hdr, data)) {
-        Except_throw(eh, "Error getting capabilities (post-setuid): [errno:%d (%s)]",
+        Er_raise(alloc, "Error getting capabilities (post-setuid): [errno:%d (%s)]",
                      errno, strerror(errno));
     }
 
@@ -90,12 +90,13 @@ void Setuid_postSetuid(struct Allocator* alloc, struct Except* eh)
     data->effective = data->permitted;
     data->inheritable = 0;
     if (capSet(hdr, data)) {
-        Except_throw(eh, "Error setting capabilities (post-setuid): [errno:%d (%s)]",
+        Er_raise(alloc, "Error setting capabilities (post-setuid): [errno:%d (%s)]",
                      errno, strerror(errno));
     }
 
     if (prctl(PR_SET_KEEPCAPS, 0)) {
-        Except_throw(eh, "Error un-keeping capabilities (post-setuid): [errno:%d (%s)]",
+        Er_raise(alloc, "Error un-keeping capabilities (post-setuid): [errno:%d (%s)]",
                      errno, strerror(errno));
     }
+    Er_ret();
 }

+ 1 - 3
util/events/Event.h

@@ -15,7 +15,6 @@
 #ifndef Event_H
 #define Event_H
 
-#include "exception/Except.h"
 #include "memory/Allocator.h"
 #include "util/events/EventBase.h"
 #include "util/Linker.h"
@@ -30,7 +29,6 @@ struct Event* Event_socketRead(void (* const callback)(void* callbackContext),
                                void* const callbackContext,
                                int s,
                                struct EventBase* base,
-                               struct Allocator* alloc,
-                               struct Except* eh);
+                               struct Allocator* alloc);
 
 #endif

+ 6 - 8
util/events/Pipe.h

@@ -60,19 +60,17 @@ struct Pipe
     #endif
 #endif
 
-struct Pipe* Pipe_named(const char* fullPath,
+Er_DEFUN(struct Pipe* Pipe_forFd(int fd,
+                        bool ipc,
                         struct EventBase* eb,
-                        struct Except* eh,
                         struct Log* log,
-                        struct Allocator* userAlloc);
+                        struct Allocator* userAlloc));
 
-struct Pipe* Pipe_forFd(int fd,
-                        bool ipc,
+Er_DEFUN(struct Pipe* Pipe_named(const char* fullPath,
                         struct EventBase* eb,
-                        struct Except* eh,
                         struct Log* log,
-                        struct Allocator* userAlloc);
+                        struct Allocator* userAlloc));
 
-bool Pipe_exists(const char* fullPath, struct Except* eh);
+Er_DEFUN(bool Pipe_exists(const char* path, struct Allocator* errAlloc));
 
 #endif

+ 5 - 7
util/events/UDPAddrIface.h

@@ -15,7 +15,7 @@
 #ifndef UDPAddrIface_H
 #define UDPAddrIface_H
 
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "interface/Iface.h"
 #include "interface/addressable/AddrIface.h"
 #include "memory/Allocator.h"
@@ -41,15 +41,13 @@ struct UDPAddrIface
  * @param base the event loop context.
  * @param bindAddr the address/port to bind to.
  * @param allocator the memory allocator for this message.
- * @param exHandler the handler to deal with whatever exception arises.
  * @param logger
  * @return a new UDPInterfaceBase.
  */
-struct UDPAddrIface* UDPAddrIface_new(struct EventBase* base,
-                                      struct Sockaddr* bindAddr,
-                                      struct Allocator* allocator,
-                                      struct Except* exHandler,
-                                      struct Log* logger);
+Er_DEFUN(struct UDPAddrIface* UDPAddrIface_new(struct EventBase* eventBase,
+                                      struct Sockaddr* addr,
+                                      struct Allocator* alloc,
+                                      struct Log* logger));
 
 int UDPAddrIface_setDSCP(struct UDPAddrIface* iface, uint8_t dscp);
 

+ 1 - 2
util/events/libuv/Event.c

@@ -58,8 +58,7 @@ struct Event* Event_socketRead(void (* const callback)(void* callbackContext),
                                void* const callbackContext,
                                int s,
                                struct EventBase* eventBase,
-                               struct Allocator* allocator,
-                               struct Except* eh)
+                               struct Allocator* allocator)
 {
     struct EventBase_pvt* base = EventBase_privatize(eventBase);
     struct Allocator* alloc = Allocator_child(allocator);

+ 25 - 29
util/events/libuv/Pipe.c

@@ -13,6 +13,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "util/events/libuv/UvWrapper.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "util/events/Pipe.h"
 #include "util/events/libuv/Pipe_pvt.h"
@@ -315,12 +316,11 @@ static int closeHandlesOnFree(struct Allocator_OnFreeJob* job)
     return 0;
 }
 
-static struct Pipe_pvt* newPipeAny(struct EventBase* eb,
+static Er_DEFUN(struct Pipe_pvt* newPipeAny(struct EventBase* eb,
                                   const char* fullPath,
                                   bool ipc,
                                   struct Log* log,
-                                  struct Except* eh,
-                                  struct Allocator* userAlloc)
+                                  struct Allocator* userAlloc))
 {
     struct EventBase_pvt* ctx = EventBase_privatize(eb);
     struct Allocator* alloc = Allocator_child(userAlloc);
@@ -339,7 +339,7 @@ static struct Pipe_pvt* newPipeAny(struct EventBase* eb,
 
     int ret = uv_pipe_init(ctx->loop, &out->peer, ipc);
     if (ret) {
-        Except_throw(eh, "uv_pipe_init() failed [%s]", uv_strerror(ret));
+        Er_raise(alloc, "uv_pipe_init() failed [%s]", uv_strerror(ret));
     }
 
     Allocator_onFree(alloc, closeHandlesOnFree, out);
@@ -348,40 +348,37 @@ static struct Pipe_pvt* newPipeAny(struct EventBase* eb,
     out->peer.data = out;
     Identity_set(out);
 
-    return out;
+    Er_ret(out);
 }
 
-struct Pipe* Pipe_forFd(int fd,
+Er_DEFUN(struct Pipe* Pipe_forFd(int fd,
                         bool ipc,
                         struct EventBase* eb,
-                        struct Except* eh,
                         struct Log* log,
-                        struct Allocator* userAlloc)
+                        struct Allocator* userAlloc))
 {
     char buff[32] = {0};
     snprintf(buff, 31, "forFd(%d)", fd);
 
-    struct Pipe_pvt* out = newPipeAny(eb, buff, ipc, log, eh, userAlloc);
+    struct Pipe_pvt* out = Er(newPipeAny(eb, buff, ipc, log, userAlloc));
 
     int ret = uv_pipe_open(&out->peer, fd);
     if (ret) {
-        Except_throw(eh, "uv_pipe_open(inFd) failed [%s]",
-                     uv_strerror(ret));
+        Er_raise(out->alloc, "uv_pipe_open(inFd) failed [%s]", uv_strerror(ret));
     }
 
     uv_connect_t req = { .handle = (uv_stream_t*) &out->peer };
     connected(&req, 0);
 
-    return &out->pub;
+    Er_ret(&out->pub);
 }
 
-struct Pipe* Pipe_named(const char* fullPath,
+Er_DEFUN(struct Pipe* Pipe_named(const char* fullPath,
                         struct EventBase* eb,
-                        struct Except* eh,
                         struct Log* log,
-                        struct Allocator* userAlloc)
+                        struct Allocator* userAlloc))
 {
-    struct Pipe_pvt* out = newPipeAny(eb, fullPath, true, log, eh, userAlloc);
+    struct Pipe_pvt* out = Er(newPipeAny(eb, fullPath, true, log, userAlloc));
 
     uv_connect_t* req = Allocator_malloc(out->alloc, sizeof(uv_connect_t));
     req->data = out;
@@ -389,40 +386,39 @@ struct Pipe* Pipe_named(const char* fullPath,
 
     int err = (&out->peer)->delayed_error;
     if (err != 0) {
-        Except_throw(eh, "uv_pipe_connect() failed [%s] for pipe [%s]",
+        Er_raise(out->alloc, "uv_pipe_connect() failed [%s] for pipe [%s]",
                      uv_strerror(err), out->pub.fullName);
     }
 
-    return &out->pub;
+    Er_ret(&out->pub);
 }
 
-struct Pipe* Pipe_serverAccept(uv_pipe_t* server,
+Er_DEFUN(struct Pipe* Pipe_serverAccept(uv_pipe_t* server,
                                const char* pipeName,
                                struct EventBase* eb,
-                               struct Except* eh,
                                struct Log* log,
-                               struct Allocator* userAlloc)
+                               struct Allocator* userAlloc))
 {
-    struct Pipe_pvt* out = newPipeAny(eb, NULL, true, log, eh, userAlloc);
+    struct Pipe_pvt* out = Er(newPipeAny(eb, NULL, true, log, userAlloc));
     int ret = uv_accept((uv_stream_t*) server, (uv_stream_t*) &out->peer);
     if (ret) {
         uv_close((uv_handle_t*) &out->peer, onClose);
-        Except_throw(eh, "uv_accept() failed: pipe [%s] [%s]",
-            pipeName, uv_strerror(ret) );
+        Er_raise(out->alloc, "uv_accept() failed: pipe [%s] [%s]",
+            pipeName, uv_strerror(ret));
     } else {
         uv_connect_t req = { .handle = (uv_stream_t*) &out->peer };
         connected(&req, 0);
     }
-    return &out->pub;
+    Er_ret(&out->pub);
 }
 
-bool Pipe_exists(const char* path, struct Except* eh)
+Er_DEFUN(bool Pipe_exists(const char* path, struct Allocator* errAlloc))
 {
     struct stat st;
     if (stat(path, &st)) {
-        if (errno == ENOENT) { return false; }
-        Except_throw(eh, "Failed stat(%s) [%s]", path, strerror(errno));
+        if (errno == ENOENT) { Er_ret(false); }
+        Er_raise(errAlloc, "Failed stat(%s) [%s]", path, strerror(errno));
     } else {
-        return (st.st_mode & S_IFMT) == S_IFSOCK;
+        Er_ret((st.st_mode & S_IFMT) == S_IFSOCK);
     }
 }

+ 7 - 8
util/events/libuv/PipeServer.c

@@ -15,7 +15,7 @@
 #include "util/events/libuv/UvWrapper.h"
 
 #include "benc/String.h"
-#include "exception/Jmp.h"
+#include "exception/Er.h"
 #include "memory/Allocator.h"
 #include "util/events/Pipe.h"
 #include "util/events/PipeServer.h"
@@ -105,15 +105,14 @@ static void onClose(uv_handle_t* handle)
 
 static struct Pipe* getPipe(struct PipeServer_pvt* psp, struct Allocator* alloc)
 {
-    struct Jmp j;
-    Jmp_try(j) {
-        return Pipe_serverAccept(
-            &psp->server, psp->pub.fullName, &psp->base->pub, &j.handler, psp->log, alloc);
-    } Jmp_catch {
+    struct Er_Ret* er = NULL;
+    struct Pipe* out = Er_check(&er, Pipe_serverAccept(
+            &psp->server, psp->pub.fullName, &psp->base->pub, psp->log, alloc));
+    if (er) {
         Log_warn(psp->log, "failed to connect to client on pipe [%s] [%s]",
-                 psp->pub.fullName, j.message);
+                 psp->pub.fullName, er->message);
     }
-    return NULL;
+    return out;
 }
 
 static int removeClientOnFree(struct Allocator_OnFreeJob* job)

+ 3 - 3
util/events/libuv/Pipe_pvt.h

@@ -17,15 +17,15 @@
 
 #include "util/events/libuv/UvWrapper.h"
 #include "util/events/Pipe.h"
+#include "exception/Er.h"
 #include "util/Linker.h"
 Linker_require("util/events/libuv/Pipe.c");
 
 #include <stdbool.h>
 
-struct Pipe* Pipe_serverAccept(uv_pipe_t* server,
+Er_DEFUN(struct Pipe* Pipe_serverAccept(uv_pipe_t* server,
                                const char* pipeName,
                                struct EventBase* eb,
-                               struct Except* eh,
                                struct Log* log,
-                               struct Allocator* userAlloc);
+                               struct Allocator* userAlloc));
 #endif

+ 6 - 8
util/events/libuv/UDPAddrIface.c

@@ -268,11 +268,10 @@ int UDPAddrIface_setBroadcast(struct UDPAddrIface* iface, bool enable)
     return uv_udp_set_broadcast(&context->uvHandle, enable ? 1 : 0);
 }
 
-struct UDPAddrIface* UDPAddrIface_new(struct EventBase* eventBase,
+Er_DEFUN(struct UDPAddrIface* UDPAddrIface_new(struct EventBase* eventBase,
                                       struct Sockaddr* addr,
                                       struct Allocator* alloc,
-                                      struct Except* exHandler,
-                                      struct Log* logger)
+                                      struct Log* logger))
 {
     struct EventBase_pvt* base = EventBase_privatize(eventBase);
 
@@ -303,15 +302,14 @@ struct UDPAddrIface* UDPAddrIface_new(struct EventBase* eventBase,
     ret = uv_udp_bind(&context->uvHandle, (const struct sockaddr*)native, 0);
 
     if (ret) {
-        Except_throw(exHandler, "call to uv_udp_bind() failed [%s]",
-                     uv_strerror(ret));
+        Er_raise(alloc, "call to uv_udp_bind() failed [%s]", uv_strerror(ret));
     }
 
     ret = uv_udp_recv_start(&context->uvHandle, allocate, incoming);
     if (ret) {
         const char* err = uv_strerror(ret);
         uv_close((uv_handle_t*) &context->uvHandle, NULL);
-        Except_throw(exHandler, "uv_udp_recv_start() failed [%s]", err);
+        Er_raise(alloc, "uv_udp_recv_start() failed [%s]", err);
     }
 
     int nameLen = sizeof(struct Sockaddr_storage);
@@ -320,7 +318,7 @@ struct UDPAddrIface* UDPAddrIface_new(struct EventBase* eventBase,
     if (ret) {
         const char* err = uv_strerror(ret);
         uv_close((uv_handle_t*) &context->uvHandle, NULL);
-        Except_throw(exHandler, "uv_udp_getsockname() failed [%s]", err);
+        Er_raise(alloc, "uv_udp_getsockname() failed [%s]", err);
     }
     ss.addr.addrLen = nameLen + 8;
 
@@ -330,5 +328,5 @@ struct UDPAddrIface* UDPAddrIface_new(struct EventBase* eventBase,
     Allocator_onFree(alloc, closeHandleOnFree, context);
     Allocator_onFree(alloc, blockFreeInsideCallback, context);
 
-    return &context->pub;
+    Er_ret(&context->pub);
 }

+ 23 - 22
util/platform/netdev/NetDev.c

@@ -20,64 +20,65 @@
 #include "util/platform/netdev/NetDev.h"
 #include "util/platform/netdev/NetPlatform.h"
 
-static void checkAddressAndPrefix(struct Sockaddr* sa,
+static Er_DEFUN(void checkAddressAndPrefix(struct Sockaddr* sa,
                                   int* addrFam,
                                   char** printedAddr,
                                   void** addr,
-                                  struct Allocator* alloc,
-                                  struct Except* eh)
+                                  struct Allocator* alloc))
 {
     *printedAddr = Sockaddr_print(sa, alloc);
     *addrFam = Sockaddr_getFamily(sa);
     if (*addrFam != Sockaddr_AF_INET && *addrFam != Sockaddr_AF_INET6) {
-        Except_throw(eh, "Unknown address type for address [%s]", *printedAddr);
+        Er_raise(alloc, "Unknown address type for address [%s]", *printedAddr);
     }
     int prefixMax = (*addrFam == Sockaddr_AF_INET6) ? 128 : 32;
     if (!(sa->flags & Sockaddr_flags_PREFIX)) {
         sa->prefix = prefixMax;
     }
     if (sa->prefix > prefixMax) {
-        Except_throw(eh, "prefix [%u] must be less than %d", sa->prefix, prefixMax);
+        Er_raise(alloc, "prefix [%u] must be less than %d", sa->prefix, prefixMax);
     }
 
     int len = Sockaddr_getAddress(sa, addr);
     if (len < 0 || len != prefixMax / 8) {
-        Except_throw(eh, "Invalid sockaddr [%s]", *printedAddr);
+        Er_raise(alloc, "Invalid sockaddr [%s]", *printedAddr);
     }
+    Er_ret();
 }
 
-void NetDev_addAddress(const char* ifName,
+Er_DEFUN(void NetDev_addAddress(const char* ifName,
                        struct Sockaddr* sa,
                        struct Log* logger,
-                       struct Except* eh)
+                       struct Allocator* alloc))
 {
     int addrFam;
     char* printedAddr;
     void* addr;
-    struct Allocator* alloc;
-    BufferAllocator_STACK(alloc, 4096);
 
-    checkAddressAndPrefix(sa, &addrFam, &printedAddr, &addr, alloc, eh);
+    Er(checkAddressAndPrefix(sa, &addrFam, &printedAddr, &addr, alloc));
 
     Log_info(logger, "Setting IP address [%s] on interface [%s]",
              printedAddr, ifName);
 
-    NetPlatform_addAddress(ifName, addr, sa->prefix, addrFam, logger, alloc, eh);
+    Er(NetPlatform_addAddress(ifName, addr, sa->prefix, addrFam, logger, alloc));
+    Er_ret();
 }
 
-void NetDev_setMTU(const char* interfaceName,
+Er_DEFUN(void NetDev_setMTU(const char* interfaceName,
                    uint32_t mtu,
                    struct Log* logger,
-                   struct Except* eh)
+                   struct Allocator* alloc))
 {
-     NetPlatform_setMTU(interfaceName, mtu, logger, eh);
+     Er(NetPlatform_setMTU(interfaceName, mtu, logger, alloc));
+     Er_ret();
 }
 
-void NetDev_flushAddresses(const char* deviceName, struct Except* eh)
+Er_DEFUN(void NetDev_flushAddresses(const char* deviceName, struct Allocator* alloc))
 {
     #ifdef win32
-        NetPlatform_flushAddresses(deviceName, eh);
+        Er(NetPlatform_flushAddresses(deviceName, alloc));
     #endif
+    Er_ret();
 }
 /*
 void NetDev_addRoute(const char* ifName,
@@ -100,21 +101,21 @@ void NetDev_addRoute(const char* ifName,
     NetPlatform_addRoute(ifName, addr, prefixLen, addrFam, logger, eh);
 }*/
 
-void NetDev_setRoutes(const char* ifName,
+Er_DEFUN(void NetDev_setRoutes(const char* ifName,
                       struct Sockaddr** prefixSet,
                       int prefixCount,
                       struct Log* logger,
-                      struct Allocator* tempAlloc,
-                      struct Except* eh)
+                      struct Allocator* tempAlloc))
 {
     for (int i = 0; i < prefixCount; i++) {
         struct Allocator* alloc = Allocator_child(tempAlloc);
         int addrFam;
         char* printedAddr;
         void* addr;
-        checkAddressAndPrefix(prefixSet[i], &addrFam, &printedAddr, &addr, alloc, eh);
+        Er(checkAddressAndPrefix(prefixSet[i], &addrFam, &printedAddr, &addr, alloc));
         Allocator_free(alloc);
     }
 
-    NetPlatform_setRoutes(ifName, prefixSet, prefixCount, logger, tempAlloc, eh);
+    Er(NetPlatform_setRoutes(ifName, prefixSet, prefixCount, logger, tempAlloc));
+    Er_ret();
 }

+ 8 - 15
util/platform/netdev/NetDev.h

@@ -29,12 +29,12 @@ Linker_require("util/platform/netdev/NetDev.c");
  * @param sa the ip address to set.
  * @param prefixLen the number of bits netmask to include in the route.
  * @param logger
- * @param eh an exception handler.
+ * @param alloc allocator for errors.
  */
-void NetDev_addAddress(const char* ifName,
+Er_DEFUN(void NetDev_addAddress(const char* ifName,
                        struct Sockaddr* sa,
                        struct Log* logger,
-                       struct Except* eh);
+                       struct Allocator* alloc));
 
 /**
  * Set the MTU of an interface.
@@ -44,26 +44,19 @@ void NetDev_addAddress(const char* ifName,
  * @param logger where to write information.
  * @param eh an exception handler.
  */
-void NetDev_setMTU(const char* interfaceName,
+Er_DEFUN(void NetDev_setMTU(const char* interfaceName,
                    uint32_t mtu,
                    struct Log* logger,
-                   struct Except* eh);
+                   struct Allocator* alloc));
 
-void NetDev_flushAddresses(const char* deviceName, struct Except* eh);
+Er_DEFUN(void NetDev_flushAddresses(const char* deviceName, struct Allocator* alloc));
 
 /**
  * Set a route to an interface.
- *
- * @param ifName the name of the interface to alter.
- * @param sa the ip address to use use for route base.
- * @param prefixLen the number of bits netmast to include in the route.
- * @param logger
- * @param eh an exception handler.
  */
-void NetDev_setRoutes(const char* ifName,
+Er_DEFUN(void NetDev_setRoutes(const char* ifName,
                       struct Sockaddr** prefixSet,
                       int prefixCount,
                       struct Log* logger,
-                      struct Allocator* tempAlloc,
-                      struct Except* eh);
+                      struct Allocator* tempAlloc));
 #endif

+ 6 - 8
util/platform/netdev/NetPlatform.h

@@ -26,23 +26,21 @@ Linker_require("util/platform/netdev/NetPlatform_" + builder.config.systemName +
 
 void NetPlatform_flushAddresses(const char* deviceName, struct Except* eh);
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh);
+                            struct Allocator* tempAlloc));
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh);
+                        struct Allocator* errAlloc));
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh);
+                           struct Allocator* tempAlloc));
 #endif

+ 50 - 49
util/platform/netdev/NetPlatform_darwin.c

@@ -62,16 +62,15 @@ Assert_compileTime(sizeof(struct sockaddr_in) == 16);
 Assert_compileTime(sizeof(struct sockaddr_dl) == 20);
 Assert_compileTime(sizeof(struct RouteMessage4) == 144);
 
-static void mkRouteMsg(struct Message* msg,
+static Er_DEFUN(void mkRouteMsg(struct Message* msg,
                        struct Sockaddr* addRoute,
                        int ifIndex,
                        const char* ifName,
                        int seq,
-                       bool delete,
-                       struct Except* eh)
+                       bool delete))
 {
     if (CString_strlen(ifName) >= 12) {
-        Except_throw(eh, "ifName [%s] too long, limit 11 chars", ifName);
+        Er_raise(msg->alloc, "ifName [%s] too long, limit 11 chars", ifName);
     }
     int lengthBegin = msg->length;
     bool ipv6 = Sockaddr_getFamily(addRoute) == Sockaddr_AF_INET6;
@@ -82,14 +81,14 @@ static void mkRouteMsg(struct Message* msg,
         };
         Bits_memset((void *)&mask.sin6_addr, 0xff, addRoute->prefix >> 3);
         ((uint8_t*)&mask.sin6_addr)[addRoute->prefix >> 3] = 0xff << (8 - (addRoute->prefix % 8));
-        Message_push(msg, &mask, sizeof(struct sockaddr_in6), eh);
+        Er(Message_epush(msg, &mask, sizeof(struct sockaddr_in6)));
     } else {
         struct sockaddr_in mask = {
             .sin_family = AF_INET,
             .sin_len = sizeof(struct sockaddr_in)
         };
         mask.sin_addr.s_addr = Endian_hostToBigEndian32(~0u << (32 - addRoute->prefix));
-        Message_push(msg, &mask, sizeof(struct sockaddr_in), eh);
+        Er(Message_epush(msg, &mask, sizeof(struct sockaddr_in)));
     }
     if (!delete) {
         struct sockaddr_dl link = {
@@ -100,12 +99,12 @@ static void mkRouteMsg(struct Message* msg,
             .sdl_nlen = CString_strlen(ifName)
         };
         CString_safeStrncpy(link.sdl_data, ifName, 12);
-        Message_push(msg, &link, sizeof(struct sockaddr_dl), eh);
+        Er(Message_epush(msg, &link, sizeof(struct sockaddr_dl)));
     }
     void* dest = Sockaddr_asNative(addRoute);
     int len = (ipv6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
     ((struct sockaddr*)dest)->sa_len = len;
-    Message_push(msg, dest, len, eh);
+    Er(Message_epush(msg, dest, len));
     struct rt_msghdr hdr = {
         .rtm_type = (delete) ? RTM_DELETE : RTM_ADD,
         .rtm_flags = RTF_UP | RTF_STATIC,
@@ -115,23 +114,23 @@ static void mkRouteMsg(struct Message* msg,
         .rtm_addrs = RTA_DST | RTA_NETMASK | ((delete) ? 0 : RTA_GATEWAY),
         .rtm_msglen = sizeof(struct rt_msghdr) + (msg->length - lengthBegin)
     };
-    Message_push(msg, &hdr, sizeof(struct rt_msghdr), eh);
+    Er(Message_epush(msg, &hdr, sizeof(struct rt_msghdr)));
+    Er_ret();
 }
 
-static void setRoutes(uint32_t ifIndex,
+static Er_DEFUN(void setRoutes(uint32_t ifIndex,
                       const char* ifName,
                       struct ArrayList_OfSockaddr* toRemove,
                       struct ArrayList_OfSockaddr* toAdd,
                       struct Log* logger,
-                      struct Allocator* alloc,
-                      struct Except* eh)
+                      struct Allocator* alloc))
 {
     int seq = 0;
     int sock = socket(PF_ROUTE, SOCK_RAW, 0);
     if (sock == -1) {
         int err = errno;
         close(sock);
-        Except_throw(eh, "open route socket [%s]", strerror(err));
+        Er_raise(alloc, "open route socket [%s]", strerror(err));
     }
     bool err = false;
     ssize_t returnLen = 0;
@@ -140,7 +139,7 @@ static void setRoutes(uint32_t ifIndex,
         struct Sockaddr* pfx = ArrayList_OfSockaddr_get(toRemove, i);
         Log_debug(logger, "DELETE ROUTE %s", Sockaddr_print(pfx, alloc));
         struct Message* msg = Message_new(0, 1024, alloc);
-        mkRouteMsg(msg, pfx, ifIndex, ifName, seq++, true, eh);
+        Er(mkRouteMsg(msg, pfx, ifIndex, ifName, seq++, true));
         //printf("DELETE ROUTE %s\n", Hex_print(msg->bytes, msg->length, alloc));
         returnLen = write(sock, msg->bytes, msg->length);
         if (returnLen < msg->length) { err = true; break; }
@@ -149,7 +148,7 @@ static void setRoutes(uint32_t ifIndex,
         struct Sockaddr* pfx = ArrayList_OfSockaddr_get(toAdd, i);
         Log_debug(logger, "ADD ROUTE %s", Sockaddr_print(pfx, alloc));
         struct Message* msg = Message_new(0, 1024, alloc);
-        mkRouteMsg(msg, pfx, ifIndex, ifName, seq++, false, eh);
+        Er(mkRouteMsg(msg, pfx, ifIndex, ifName, seq++, false));
         //printf("ADD ROUTE %s\n", Hex_print(msg->bytes, msg->length, alloc));
         returnLen = write(sock, msg->bytes, msg->length);
         if (returnLen < msg->length) { err = true; break; }
@@ -158,12 +157,13 @@ static void setRoutes(uint32_t ifIndex,
     if (returnLen < 0) {
         int error = errno;
         close(sock);
-        Except_throw(eh, "setRoutes() [%s]", strerror(error));
+        Er_raise(alloc, "setRoutes() [%s]", strerror(error));
     } else if (err) {
         close(sock);
-        Except_throw(eh, "setRoutes() returned short");
+        Er_raise(alloc, "setRoutes() returned short");
     }
     close(sock);
+    Er_ret();
 }
 
 static int prefixFromWeirdBSDMask(uint8_t* weirdBsdMask, bool ipv6)
@@ -183,20 +183,19 @@ static int prefixFromWeirdBSDMask(uint8_t* weirdBsdMask, bool ipv6)
     return out + Bits_popCountx32(weirdBsdMask[len - 1]);
 }
 
-static struct ArrayList_OfSockaddr* getRoutes(uint32_t ifIndex,
+static Er_DEFUN(struct ArrayList_OfSockaddr* getRoutes(uint32_t ifIndex,
                                               struct Log* logger,
-                                              struct Allocator* allocator,
-                                              struct Except* eh)
+                                              struct Allocator* allocator))
 {
     size_t needed;
     int mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0 };
     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
-        Except_throw(eh, "sysctl(net.route.0.0.dump) estimate");
+        Er_raise(allocator, "sysctl(net.route.0.0.dump) estimate");
     }
     struct Allocator* tempAlloc = Allocator_child(allocator);
     uint8_t* buf = Allocator_malloc(tempAlloc, needed);
     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
-        Except_throw(eh, "sysctl(net.route.0.0.dump)");
+        Er_raise(allocator, "sysctl(net.route.0.0.dump)");
     }
     struct ArrayList_OfSockaddr* addrList = ArrayList_OfSockaddr_new(allocator);
     for (int i = 0; i < (int)needed;) {
@@ -226,15 +225,14 @@ static struct ArrayList_OfSockaddr* getRoutes(uint32_t ifIndex,
         ArrayList_OfSockaddr_add(addrList, addr);
     }
     Allocator_free(tempAlloc);
-    return addrList;
+    Er_ret(addrList);
 }
 
-static void addIp4Address(const char* interfaceName,
+static Er_DEFUN(void addIp4Address(const char* interfaceName,
                           const uint8_t address[4],
                           int prefixLen,
                           struct Log* logger,
-                          struct Allocator* tempAlloc,
-                          struct Except* eh)
+                          struct Allocator* tempAlloc))
 {
     struct ifaliasreq ifarted;
     Bits_memset(&ifarted, 0, sizeof(struct ifaliasreq));
@@ -248,7 +246,7 @@ static void addIp4Address(const char* interfaceName,
 
     int s = socket(AF_INET, SOCK_DGRAM, 0);
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(tempAlloc, "socket() [%s]", strerror(errno));
     }
 
     // will probably fail, ignore result.
@@ -259,7 +257,7 @@ static void addIp4Address(const char* interfaceName,
     if (ioctl(s, SIOCSIFADDR, &ifarted) < 0) {
         int err = errno;
         close(s);
-        Except_throw(eh, "ioctl(SIOCSIFADDR) [%s]", strerror(err));
+        Er_raise(tempAlloc, "ioctl(SIOCSIFADDR) [%s]", strerror(err));
     }
 
     //setupRoute4(address, prefixLen, interfaceName, logger, tempAlloc, eh);
@@ -268,13 +266,14 @@ static void addIp4Address(const char* interfaceName,
         address[0], address[1], address[2], address[3], prefixLen, interfaceName);
 
     close(s);
+    Er_ret();
 }
 
-static void addIp6Address(const char* interfaceName,
+static Er_DEFUN(void addIp6Address(const char* interfaceName,
                           const uint8_t address[16],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* errAlloc))
 {
     /* stringify our IP address */
     char myIp[40];
@@ -294,7 +293,7 @@ static void addIp6Address(const char* interfaceName,
     int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
     if (err) {
         // Should never happen since the address is specified as binary.
-        Except_throw(eh, "bad IPv6 address [%s]", gai_strerror(err));
+        Er_raise(errAlloc, "bad IPv6 address [%s]", gai_strerror(err));
     }
 
     bcopy(result->ai_addr, &in6_addreq.ifra_addr, result->ai_addrlen);
@@ -316,46 +315,47 @@ static void addIp6Address(const char* interfaceName,
     /* do the actual assignment ioctl */
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(errAlloc, "socket() [%s]", strerror(errno));
     }
 
     if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
         int err = errno;
         close(s);
-        Except_throw(eh, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
+        Er_raise(errAlloc, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
     }
 
     Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName);
 
     close(s);
+    Er_ret();
 }
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     if (addrFam == Sockaddr_AF_INET6) {
-        addIp6Address(interfaceName, address, prefixLen, logger, eh);
+        Er(addIp6Address(interfaceName, address, prefixLen, logger, tempAlloc));
     } else if (addrFam == Sockaddr_AF_INET) {
-        addIp4Address(interfaceName, address, prefixLen, logger, tempAlloc, eh);
+        Er(addIp4Address(interfaceName, address, prefixLen, logger, tempAlloc));
     } else {
         Assert_true(0);
     }
+    Er_ret();
 }
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh)
+                        struct Allocator* errAlloc))
 {
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
 
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(errAlloc, "socket() [%s]", strerror(errno));
     }
 
     struct ifreq ifRequest;
@@ -368,17 +368,17 @@ void NetPlatform_setMTU(const char* interfaceName,
     if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
        int err = errno;
        close(s);
-       Except_throw(eh, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
+       Er_raise(errAlloc, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
     }
     close(s);
+    Er_ret();
 }
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh)
+                           struct Allocator* tempAlloc))
 {
     struct ArrayList_OfSockaddr* newRoutes = ArrayList_OfSockaddr_new(tempAlloc);
     for (int i = 0; i < prefixCount; i++) {
@@ -388,14 +388,15 @@ void NetPlatform_setRoutes(const char* ifName,
         } else if (addrFam == Sockaddr_AF_INET6) {
             // OK
         } else {
-            Except_throw(eh, "Unrecognized address type %d", addrFam);
+            Er_raise(tempAlloc, "Unrecognized address type %d", addrFam);
         }
         ArrayList_OfSockaddr_add(newRoutes, prefixSet[i]);
     }
     uint32_t ifIndex = if_nametoindex(ifName);
     if (!ifIndex) {
-        Except_throw(eh, "tunName not recognized");
+        Er_raise(tempAlloc, "tunName not recognized");
     }
-    struct ArrayList_OfSockaddr* oldRoutes = getRoutes(ifIndex, logger, tempAlloc, eh);
-    setRoutes(ifIndex, ifName, oldRoutes, newRoutes, logger, tempAlloc, eh);
+    struct ArrayList_OfSockaddr* oldRoutes = Er(getRoutes(ifIndex, logger, tempAlloc));
+    Er(setRoutes(ifIndex, ifName, oldRoutes, newRoutes, logger, tempAlloc));
+    Er_ret();
 }

+ 26 - 25
util/platform/netdev/NetPlatform_freebsd.c

@@ -13,7 +13,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "util/platform/netdev/NetPlatform.h"
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "util/AddrTools.h"
 #include "util/platform/Sockaddr.h"
 #include "util/CString.h"
@@ -39,11 +39,11 @@
 #include <netinet6/nd6.h>
 #include <arpa/inet.h>
 
-static void addIp4Address(const char* interfaceName,
+static Er_DEFUN(void addIp4Address(const char* interfaceName,
                           const uint8_t address[4],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
     struct ifaliasreq ifaliasreq;
     struct sockaddr_in* in;
@@ -65,7 +65,7 @@ static void addIp4Address(const char* interfaceName,
 
     int err = inet_aton(myIp, &in->sin_addr);
     if (err == 0){
-      Except_throw(eh, "inet_aton(myIp) failed");
+      Er_raise(alloc, "inet_aton(myIp) failed");
     }
 
     in = (struct sockaddr_in *) &ifaliasreq.ifra_mask;
@@ -74,7 +74,7 @@ static void addIp4Address(const char* interfaceName,
 
     err = inet_aton(myMask, &in->sin_addr);
     if (err == 0){
-      Except_throw(eh, "inet_aton(myMask) failed");
+      Er_raise(alloc, "inet_aton(myMask) failed");
     }
 
     in = (struct sockaddr_in *) &ifaliasreq.ifra_broadaddr;
@@ -89,21 +89,21 @@ static void addIp4Address(const char* interfaceName,
     if (ioctl(s, SIOCAIFADDR, &ifaliasreq) == -1){
       int err = errno;
       close(s);
-      Except_throw(eh, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
+      Er_raise(alloc, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
     }
 
     Log_info(logger, "Configured IPv4 [%s/%s] for [%s]", myIp, myMask, interfaceName);
 
     close(s);
 
-
+    Er_ret();
 }
 
-static void addIp6Address(const char* interfaceName,
+static Er_DEFUN(void addIp6Address(const char* interfaceName,
                           const uint8_t address[16],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
     /* stringify our IP address */
     char myIp[40];
@@ -123,7 +123,7 @@ static void addIp6Address(const char* interfaceName,
     int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
     if (err) {
         // Should never happen since the address is specified as binary.
-        Except_throw(eh, "bad IPv6 address [%s]", gai_strerror(err));
+        Er_raise(alloc, "bad IPv6 address [%s]", gai_strerror(err));
     }
 
     memcpy(&in6_addreq.ifra_addr, result->ai_addr, result->ai_addrlen);
@@ -149,46 +149,47 @@ static void addIp6Address(const char* interfaceName,
     /* do the actual assignment ioctl */
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(alloc, "socket() [%s]", strerror(errno));
     }
 
     if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
         int err = errno;
         close(s);
-        Except_throw(eh, "ioctl(SIOCAIFADDR) [%s]", strerror(err));
+        Er_raise(alloc, "ioctl(SIOCAIFADDR) [%s]", strerror(err));
     }
 
     Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName);
 
     close(s);
+    Er_ret();
 }
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     if (addrFam == Sockaddr_AF_INET6) {
-        addIp6Address(interfaceName, address, prefixLen, logger, eh);
+        Er(addIp6Address(interfaceName, address, prefixLen, logger, tempAlloc));
     } else if (addrFam == Sockaddr_AF_INET) {
-        addIp4Address(interfaceName, address, prefixLen, logger, eh);
+        Er(addIp4Address(interfaceName, address, prefixLen, logger, tempAlloc));
     } else {
         Assert_true(0);
     }
+    Er_ret();
 }
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh)
+                        struct Allocator* errAlloc))
 {
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
 
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(errAlloc, "socket() [%s]", strerror(errno));
     }
 
 
@@ -202,16 +203,16 @@ void NetPlatform_setMTU(const char* interfaceName,
     if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
        int err = errno;
        close(s);
-       Except_throw(eh, "ioctl(SIOCSIFMTU) failed [%s]", strerror(err));
+       Er_raise(errAlloc, "ioctl(SIOCSIFMTU) failed [%s]", strerror(err));
     }
+    Er_ret();
 }
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh)
+                           struct Allocator* tempAlloc))
 {
-    Except_throw(eh, "NetPlatform_setRoutes is not implemented in this platform.");
+    Er_raise(tempAlloc, "NetPlatform_setRoutes is not implemented in this platform.");
 }

+ 71 - 71
util/platform/netdev/NetPlatform_linux.c

@@ -67,15 +67,15 @@ struct Cjdns_in6_ifreq
  * @param ifRequestOut an ifreq which will be populated with the interface index of the interface.
  * @return a socket for interacting with this interface.
  */
-static int socketForIfName(const char* interfaceName,
+static Er_DEFUN(int socketForIfName(const char* interfaceName,
                            int af,
-                           struct Except* eh,
-                           struct ifreq* ifRequestOut)
+                           struct Allocator* alloc,
+                           struct ifreq* ifRequestOut))
 {
     int s;
 
     if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(alloc, "socket() [%s]", strerror(errno));
     }
 
     memset(ifRequestOut, 0, sizeof(struct ifreq));
@@ -84,34 +84,34 @@ static int socketForIfName(const char* interfaceName,
     if (ioctl(s, SIOCGIFINDEX, ifRequestOut) < 0) {
         int err = errno;
         close(s);
-        Except_throw(eh, "ioctl(SIOCGIFINDEX) [%s]", strerror(err));
+        Er_raise(alloc, "ioctl(SIOCGIFINDEX) [%s]", strerror(err));
     }
-    return s;
+    Er_ret(s);
 }
 
 /** don't use if_nametoindex() because it accesses the filesystem. */
-static int ifIndexForName(const char* interfaceName, struct Except* eh)
+static Er_DEFUN(int ifIndexForName(const char* interfaceName, struct Allocator* alloc))
 {
     struct ifreq ifRequest;
-    int s = socketForIfName(interfaceName, AF_INET, eh, &ifRequest);
+    int s = Er(socketForIfName(interfaceName, AF_INET, alloc, &ifRequest));
     close(s);
-    return ifRequest.ifr_ifindex;
+    Er_ret(ifRequest.ifr_ifindex);
 }
 
-static void checkInterfaceUp(int socket,
+static Er_DEFUN(void checkInterfaceUp(int socket,
                              struct ifreq* ifRequest,
                              struct Log* logger,
-                             struct Except* eh)
+                             struct Allocator* alloc))
 {
     if (ioctl(socket, SIOCGIFFLAGS, ifRequest) < 0) {
         int err = errno;
         close(socket);
-        Except_throw(eh, "ioctl(SIOCGIFFLAGS) [%s]", strerror(err));
+        Er_raise(alloc, "ioctl(SIOCGIFFLAGS) [%s]", strerror(err));
     }
 
     if (ifRequest->ifr_flags & IFF_UP & IFF_RUNNING) {
         // already up.
-        return;
+        Er_ret();
     }
 
     Log_info(logger, "Bringing up interface [%s]", ifRequest->ifr_name);
@@ -120,24 +120,24 @@ static void checkInterfaceUp(int socket,
     if (ioctl(socket, SIOCSIFFLAGS, ifRequest) < 0) {
         int err = errno;
         close(socket);
-        Except_throw(eh, "ioctl(SIOCSIFFLAGS) [%s]", strerror(err));
+        Er_raise(alloc, "ioctl(SIOCSIFFLAGS) [%s]", strerror(err));
     }
+    Er_ret();
 }
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     struct ifreq ifRequest;
-    int s = socketForIfName(interfaceName, addrFam, eh, &ifRequest);
+    int s = Er(socketForIfName(interfaceName, addrFam, tempAlloc, &ifRequest));
     int ifIndex = ifRequest.ifr_ifindex;
 
     // checkInterfaceUp() clobbers the ifindex.
-    checkInterfaceUp(s, &ifRequest, logger, eh);
+    Er(checkInterfaceUp(s, &ifRequest, logger, tempAlloc));
 
     if (addrFam == Sockaddr_AF_INET6) {
         struct Cjdns_in6_ifreq ifr6 = {
@@ -150,9 +150,9 @@ void NetPlatform_addAddress(const char* interfaceName,
             int err = errno;
             close(s);
             if (err == EPERM) {
-                  Except_throw(eh, "ioctl permission denied, Are you root and is ipv6 enabled?");
+                Er_raise(tempAlloc, "ioctl permission denied, Are you root and is ipv6 enabled?");
             } else {
-                  Except_throw(eh, "ioctl(SIOCSIFADDR) failed: [%s]", strerror(err));
+                Er_raise(tempAlloc, "ioctl(SIOCSIFADDR) failed: [%s]", strerror(err));
             }
         }
 
@@ -165,7 +165,7 @@ void NetPlatform_addAddress(const char* interfaceName,
         if (ioctl(s, SIOCSIFADDR, &ifRequest) < 0) {
             int err = errno;
             close(s);
-            Except_throw(eh, "ioctl(SIOCSIFADDR) failed: [%s]", strerror(err));
+            Er_raise(tempAlloc, "ioctl(SIOCSIFADDR) failed: [%s]", strerror(err));
         }
 
         uint32_t x = (uint32_t)~0 << (32 - prefixLen);
@@ -176,22 +176,23 @@ void NetPlatform_addAddress(const char* interfaceName,
         if (ioctl(s, SIOCSIFNETMASK, &ifRequest) < 0) {
             int err = errno;
             close(s);
-            Except_throw(eh, "ioctl(SIOCSIFNETMASK) failed: [%s]", strerror(err));
+            Er_raise(tempAlloc, "ioctl(SIOCSIFNETMASK) failed: [%s]", strerror(err));
         }
     } else {
         Assert_true(0);
     }
 
     close(s);
+    Er_ret();
 }
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh)
+                        struct Allocator* alloc))
 {
     struct ifreq ifRequest;
-    int s = socketForIfName(interfaceName, AF_INET6, eh, &ifRequest);
+    int s = Er(socketForIfName(interfaceName, AF_INET6, alloc, &ifRequest));
 
     Log_info(logger, "Setting MTU for device [%s] to [%u] bytes.", interfaceName, mtu);
 
@@ -199,10 +200,11 @@ void NetPlatform_setMTU(const char* interfaceName,
     if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
         int err = errno;
         close(s);
-        Except_throw(eh, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
+        Er_raise(alloc, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
     }
 
     close(s);
+    Er_ret();
 }
 
 struct IfIndexAttr {
@@ -231,20 +233,19 @@ struct RouteInfo {
 
 #define BUFF_SZ 16384
 
-static bool getMoreMessages(struct RouteInfo** rio,
+static Er_DEFUN(bool getMoreMessages(struct RouteInfo** rio,
                             int sock,
                             int ifIndex,
-                            struct Allocator* alloc,
-                            struct Except* eh)
+                            struct Allocator* alloc))
 {
     bool retVal = false;
     struct Allocator* tempAlloc = Allocator_child(alloc);
     struct Message* msg = Message_new(BUFF_SZ, 0, tempAlloc);
     ssize_t sz = recv(sock, msg->bytes, BUFF_SZ, MSG_TRUNC);
     if (sz < (ssize_t)sizeof(struct nlmsghdr)) {
-        Except_throw(eh, "recv() -> %s", strerror(errno));
+        Er_raise(tempAlloc, "recv() -> %s", strerror(errno));
     } else if (sz > BUFF_SZ) {
-        Except_throw(eh, "recv() -> buffer too small");
+        Er_raise(tempAlloc, "recv() -> buffer too small");
     }
 
     msg->length = sz;
@@ -254,15 +255,15 @@ static bool getMoreMessages(struct RouteInfo** rio,
         struct RouteInfo ri = { .protocol = 0 };
         int initMsgLen = msg->length;
         struct nlmsghdr hdr;
-        Message_pop(msg, &hdr, sizeof(struct nlmsghdr), eh);
+        Er(Message_epop(msg, &hdr, sizeof(struct nlmsghdr)));
         //printf("\nHEADER %04x %04x\n", hdr.nlmsg_type, hdr.nlmsg_flags);
         if (hdr.nlmsg_flags & NLM_F_MULTI) { retVal = true; }
         if (hdr.nlmsg_type == NLMSG_DONE) {
             Allocator_free(tempAlloc);
-            return false;
+            Er_ret(false);
         }
         struct rtmsg rtm;
-        Message_pop(msg, &rtm, sizeof(struct rtmsg), eh);
+        Er(Message_epop(msg, &rtm, sizeof(struct rtmsg)));
         ri.prefix = rtm.rtm_dst_len;
         ri.af = rtm.rtm_family;
         ri.protocol = rtm.rtm_protocol;
@@ -271,35 +272,35 @@ static bool getMoreMessages(struct RouteInfo** rio,
             if (remainingLen <= (int)sizeof(struct rtattr)) { break; }
             struct rtattr attrHead;
             //printf(">%s %d\n", Hex_print(msg->bytes, msg->length, tempAlloc), remainingLen);
-            Message_pop(msg, &attrHead, sizeof(struct rtattr), eh);
+            Er(Message_epop(msg, &attrHead, sizeof(struct rtattr)));
             switch (attrHead.rta_type) {
                 case RTA_OIF: {
                     if (attrHead.rta_len != 8) {
-                        Except_throw(eh, "unexpected rta_len for ifIndex");
+                        Er_raise(alloc, "unexpected rta_len for ifIndex");
                     }
-                    Message_pop(msg, &ri.ifIndex, 4, eh);
+                    Er(Message_epop(msg, &ri.ifIndex, 4));
                     break;
                 }
                 case RTA_DST: {
                     if (rtm.rtm_family == AF_INET6) {
                         if (attrHead.rta_len != 20) {
-                            Except_throw(eh, "unexpected rta_len for RTA_DST (ipv6)");
+                            Er_raise(alloc, "unexpected rta_len for RTA_DST (ipv6)");
                         }
-                        Message_pop(msg, ri.dstAddr, 16, eh);
+                        Er(Message_epop(msg, ri.dstAddr, 16));
                     } else if (rtm.rtm_family == AF_INET) {
                         if (attrHead.rta_len != 8) {
-                            Except_throw(eh, "unexpected rta_len for RTA_DST (ipv4)");
+                            Er_raise(alloc, "unexpected rta_len for RTA_DST (ipv4)");
                         }
-                        Message_pop(msg, ri.dstAddr, 4, eh);
+                        Er(Message_epop(msg, ri.dstAddr, 4));
                     } else {
-                        Except_throw(eh, "unexpected af %d", rtm.rtm_family);
+                        Er_raise(alloc, "unexpected af %d", rtm.rtm_family);
                     }
                     break;
                 }
                 default: {
                     int effectiveLen = RTA_ALIGN(attrHead.rta_len);
                     //printf("unrecognized %d (length %d)\n", attrHead.rta_type, effectiveLen);
-                    Message_pop(msg, NULL, effectiveLen - sizeof(struct rtattr), eh);
+                    Er(Message_epop(msg, NULL, effectiveLen - sizeof(struct rtattr)));
                     break;
                 }
             }
@@ -315,13 +316,12 @@ static bool getMoreMessages(struct RouteInfo** rio,
         *rio = outRi;
     }
     Allocator_free(tempAlloc);
-    return retVal;
+    Er_ret(retVal);
 }
 
-static struct RouteInfo* getRoutes(int sock,
+static Er_DEFUN(struct RouteInfo* getRoutes(int sock,
                                    int ifIndex,
-                                   struct Allocator* alloc,
-                                   struct Except* eh)
+                                   struct Allocator* alloc))
 {
     struct RouteRequest req = {
         .hdr = {
@@ -335,11 +335,11 @@ static struct RouteInfo* getRoutes(int sock,
     };
     ssize_t sz = send(sock, &req, req.hdr.nlmsg_len, 0);
     if (sz < 0) {
-        Except_throw(eh, "send() -> %s", strerror(errno));
+        Er_raise(alloc, "send() -> %s", strerror(errno));
     }
     struct RouteInfo* ri = NULL;
-    while (getMoreMessages(&ri, sock, ifIndex, alloc, eh)) ;
-    return ri;
+    while (Er(getMoreMessages(&ri, sock, ifIndex, alloc))) ;
+    Er_ret(ri);
 }
 
 static void bitShave(uint8_t* address, int prefix, int af)
@@ -360,11 +360,10 @@ static void bitShave(uint8_t* address, int prefix, int af)
     }
 }
 
-static void addDeleteRoutes(int sock,
+static Er_DEFUN(void addDeleteRoutes(int sock,
                             bool delete,
                             struct RouteInfo* ri,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     struct Message* msg = Message_new(0, 512, tempAlloc);
     for (;ri;ri = ri->next) {
@@ -375,12 +374,12 @@ static void addDeleteRoutes(int sock,
             },
             .ifIndex = ri->ifIndex
         };
-        Message_push(msg, &ifa, sizeof(struct IfIndexAttr), NULL);
+        Er(Message_epush(msg, &ifa, sizeof(struct IfIndexAttr)));
         int addrLen = (ri->af == AF_INET6) ? 16 : 4;
-        Message_push(msg, ri->dstAddr, addrLen, NULL);
+        Er(Message_epush(msg, ri->dstAddr, addrLen));
         bitShave(msg->bytes, ri->prefix, ri->af);
         struct rtattr rta = { .rta_len = sizeof(struct rtattr) + addrLen, .rta_type = RTA_DST };
-        Message_push(msg, &rta, sizeof(struct rtattr), NULL);
+        Er(Message_epush(msg, &rta, sizeof(struct rtattr)));
         struct rtmsg route = {
             .rtm_family = ri->af,
             .rtm_dst_len = ri->prefix,
@@ -389,19 +388,20 @@ static void addDeleteRoutes(int sock,
             .rtm_protocol = (delete) ? RTPROT_UNSPEC : ri->protocol,
             .rtm_type = (delete) ? RTN_UNSPEC : RTN_UNICAST
         };
-        Message_push(msg, &route, sizeof(struct rtmsg), NULL);
+        Er(Message_epush(msg, &route, sizeof(struct rtmsg)));
         struct nlmsghdr hdr = {
             .nlmsg_len = msg->length + sizeof(struct nlmsghdr),
             .nlmsg_type = (delete) ? RTM_DELROUTE : RTM_NEWROUTE,
             .nlmsg_flags = NLM_F_REQUEST | ((delete) ? 0 : NLM_F_CREATE) // | NLM_F_ACK,
         };
-        Message_push(msg, &hdr, sizeof(struct nlmsghdr), NULL);
+        Er(Message_epush(msg, &hdr, sizeof(struct nlmsghdr)));
         ssize_t sz = send(sock, msg->bytes, msg->length, 0);
         if (sz < 0) {
-            Except_throw(eh, "send() -> %s", strerror(errno));
+            Er_raise(tempAlloc, "send() -> %s", strerror(errno));
         }
         Message_reset(msg);
     }
+    Er_ret();
 }
 
 static int closeSocket(struct Allocator_OnFreeJob* job)
@@ -411,14 +411,14 @@ static int closeSocket(struct Allocator_OnFreeJob* job)
     return 0;
 }
 
-static int mkSocket(struct Allocator* alloc, struct Except* eh)
+static Er_DEFUN(int mkSocket(struct Allocator* alloc))
 {
     int sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
     if (sock < 0) {
-        Except_throw(eh, "socket(PF_NETLINK) -> %s", strerror(errno));
+        Er_raise(alloc, "socket(PF_NETLINK) -> %s", strerror(errno));
     }
     Allocator_onFree(alloc, closeSocket, (void*) ((long) sock));
-    return sock;
+    Er_ret(sock);
 }
 
 static struct RouteInfo* riForSockaddrs(struct Sockaddr** prefixSet,
@@ -457,19 +457,19 @@ static void logRis(struct RouteInfo* ri, struct Log* logger, char* msg)
     }
 }
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh)
+                           struct Allocator* tempAlloc))
 {
-    int ifIndex = ifIndexForName(ifName, eh);
+    int ifIndex = Er(ifIndexForName(ifName, tempAlloc));
     struct RouteInfo* newRi = riForSockaddrs(prefixSet, prefixCount, ifIndex, tempAlloc);
-    int sock = mkSocket(tempAlloc, eh);
-    struct RouteInfo* oldRi = getRoutes(sock, ifIndex, tempAlloc, eh);
+    int sock = Er(mkSocket(tempAlloc));
+    struct RouteInfo* oldRi = Er(getRoutes(sock, ifIndex, tempAlloc));
     logRis(oldRi, logger, "DELETE ROUTE");
-    addDeleteRoutes(sock, true, oldRi, tempAlloc, eh);
+    Er(addDeleteRoutes(sock, true, oldRi, tempAlloc));
     logRis(newRi, logger, "ADD ROUTE");
-    addDeleteRoutes(sock, false, newRi, tempAlloc, eh);
+    Er(addDeleteRoutes(sock, false, newRi, tempAlloc));
+    Er_ret();
 }

+ 24 - 23
util/platform/netdev/NetPlatform_netbsd.c

@@ -12,7 +12,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "util/platform/netdev/NetPlatform.h"
 #include "util/AddrTools.h"
 #include "util/platform/Sockaddr.h"
@@ -37,20 +37,20 @@
 #include <netinet6/in6_var.h>
 #include <netinet6/nd6.h>
 
-static void addIp4Address(const char* interfaceName,
+static Er_DEFUN(void addIp4Address(const char* interfaceName,
                           const uint8_t address[4],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
-    Except_throw(eh, "unimplemented");
+    Er_raise(alloc, "unimplemented");
 }
 
-static void addIp6Address(const char* interfaceName,
+static Er_DEFUN(void addIp6Address(const char* interfaceName,
                           const uint8_t address[16],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
     /* stringify our IP address */
     char myIp[40];
@@ -70,7 +70,7 @@ static void addIp6Address(const char* interfaceName,
     int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
     if (err) {
         // Should never happen since the address is specified as binary.
-        Except_throw(eh, "bad IPv6 address [%s]", gai_strerror(err));
+        Er_raise(alloc, "bad IPv6 address [%s]", gai_strerror(err));
     }
 
     memcpy(&in6_addreq.ifra_addr, result->ai_addr, result->ai_addrlen);
@@ -96,46 +96,47 @@ static void addIp6Address(const char* interfaceName,
     /* do the actual assignment ioctl */
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(alloc, "socket() [%s]", strerror(errno));
     }
 
     if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
         int err = errno;
         close(s);
-        Except_throw(eh, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
+        Er_raise(alloc, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
     }
 
     Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName);
 
     close(s);
+    Er_ret();
 }
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     if (addrFam == Sockaddr_AF_INET6) {
-        addIp6Address(interfaceName, address, prefixLen, logger, eh);
+        addIp6Address(interfaceName, address, prefixLen, logger, tempAlloc);
     } else if (addrFam == Sockaddr_AF_INET) {
-        addIp4Address(interfaceName, address, prefixLen, logger, eh);
+        addIp4Address(interfaceName, address, prefixLen, logger, tempAlloc);
     } else {
         Assert_true(0);
     }
+    Er_ret();
 }
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh)
+                        struct Allocator* errAlloc))
 {
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
 
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(errAlloc, "socket() [%s]", strerror(errno));
     }
 
 
@@ -149,16 +150,16 @@ void NetPlatform_setMTU(const char* interfaceName,
     if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
        int err = errno;
        close(s);
-       Except_throw(eh, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
+       Er_raise(errAlloc, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
     }
+    Er_ret();
 }
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh)
+                           struct Allocator* tempAlloc))
 {
-    Except_throw(eh, "NetPlatform_setRoutes is not implemented in this platform.");
-}
+    Er_raise(tempAlloc, "NetPlatform_setRoutes is not implemented in this platform.");
+}

+ 22 - 22
util/platform/netdev/NetPlatform_openbsd.c

@@ -12,7 +12,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
-#include "exception/Except.h"
+#include "exception/Er.h"
 #include "util/platform/netdev/NetPlatform.h"
 #include "util/AddrTools.h"
 #include "util/platform/Sockaddr.h"
@@ -37,20 +37,20 @@
 #include <netinet6/in6_var.h>
 #include <netinet6/nd6.h>
 
-static void addIp4Address(const char* interfaceName,
+static Er_DEFUN(void addIp4Address(const char* interfaceName,
                           const uint8_t address[4],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
-    Except_throw(eh, "unimplemented");
+    Er_raise(alloc, "unimplemented");
 }
 
-static void addIp6Address(const char* interfaceName,
+static Er_DEFUN(void addIp6Address(const char* interfaceName,
                           const uint8_t address[16],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
     /* stringify our IP address */
     char myIp[40];
@@ -70,7 +70,7 @@ static void addIp6Address(const char* interfaceName,
     int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
     if (err) {
         // Should never happen since the address is specified as binary.
-        Except_throw(eh, "bad IPv6 address [%s]", gai_strerror(err));
+        Er_raise(alloc, "bad IPv6 address [%s]", gai_strerror(err));
     }
 
     memcpy(&in6_addreq.ifra_addr, result->ai_addr, result->ai_addrlen);
@@ -96,46 +96,47 @@ static void addIp6Address(const char* interfaceName,
     /* do the actual assignment ioctl */
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(alloc, "socket() [%s]", strerror(errno));
     }
 
     if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
         int err = errno;
         close(s);
-        Except_throw(eh, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
+        Er_raise(alloc, "ioctl(SIOCAIFADDR) [%s] for [%s]", strerror(err), interfaceName);
     }
 
     Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName);
 
     close(s);
+    Er_ret();
 }
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     if (addrFam == Sockaddr_AF_INET6) {
-        addIp6Address(interfaceName, address, prefixLen, logger, eh);
+        addIp6Address(interfaceName, address, prefixLen, logger, tempAlloc);
     } else if (addrFam == Sockaddr_AF_INET) {
-        addIp4Address(interfaceName, address, prefixLen, logger, eh);
+        addIp4Address(interfaceName, address, prefixLen, logger, tempAlloc);
     } else {
         Assert_true(0);
     }
+    Er_ret();
 }
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh)
+                        struct Allocator* errAlloc))
 {
     int s = socket(AF_INET6, SOCK_DGRAM, 0);
 
     if (s < 0) {
-        Except_throw(eh, "socket() [%s]", strerror(errno));
+        Er_raise(errAlloc, "socket() [%s]", strerror(errno));
     }
 
 
@@ -149,16 +150,15 @@ void NetPlatform_setMTU(const char* interfaceName,
     if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
        int err = errno;
        close(s);
-       Except_throw(eh, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
+       Er_raise(errAlloc, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
     }
 }
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh)
+                           struct Allocator* tempAlloc))
 {
-    Except_throw(eh, "NetPlatform_setRoutes is not implemented in this platform.");
+    Er_raise(tempAlloc, "NetPlatform_setRoutes is not implemented in this platform.");
 }

+ 27 - 27
util/platform/netdev/NetPlatform_sunos.c

@@ -12,6 +12,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
+#include "exception/Er.h"
 #include "util/platform/netdev/NetPlatform.h"
 #include "util/Assert.h"
 #include "util/platform/Sockaddr.h"
@@ -55,10 +56,10 @@ struct RouteMessage {
 };
 Assert_compileTime(sizeof(struct RouteMessage) == 172);
 
-static void setupRoute(const uint8_t address[16],
+static Er_DEFUN(void setupRoute(const uint8_t address[16],
                        int prefixLen,
                        struct Log* logger,
-                       struct Except* eh)
+                       struct Allocator* alloc))
 {
     struct RouteMessage rm = {
         .header = {
@@ -85,34 +86,34 @@ static void setupRoute(const uint8_t address[16],
 
     int sock = socket(PF_ROUTE, SOCK_RAW, 0);
     if (sock == -1) {
-        Except_throw(eh, "open route socket [%s]", strerror(errno));
+        Er_raise(alloc, "open route socket [%s]", strerror(errno));
     }
 
     ssize_t returnLen = write(sock, (char*) &rm, rm.header.rtm_msglen);
     if (returnLen < 0) {
-        Except_throw(eh, "insert route [%s]", strerror(errno));
+        Er_raise(alloc, "insert route [%s]", strerror(errno));
     } else if (returnLen < rm.header.rtm_msglen) {
-        Except_throw(eh,
-                     "insert route returned only [%d] of [%d]",
+        Er_raise(alloc, "insert route returned only [%d] of [%d]",
                      (int)returnLen, rm.header.rtm_msglen);
     }
+    Er_ret();
 }
 
-static void addIp4Address(const char* interfaceName,
+static Er_DEFUN(void addIp4Address(const char* interfaceName,
                           const uint8_t address[4],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
     // TODO(cjd): implement this and then remove the exception from TUNInterface_ipv4_root_test.c
-    Except_throw(eh, "unimplemented");
+    Er_raise(alloc, "unimplemented");
 }
 
-static void addIp6Address(const char* interfaceName,
+static Er_DEFUN(void addIp6Address(const char* interfaceName,
                           const uint8_t address[16],
                           int prefixLen,
                           struct Log* logger,
-                          struct Except* eh)
+                          struct Allocator* alloc))
 {
     struct lifreq ifr = {
         .lifr_ppa = 0,
@@ -156,45 +157,44 @@ static void addIp6Address(const char* interfaceName,
     if (error) {
         int err = errno;
         close(udpSock);
-        Except_throw(eh, "%s [%s]",
-                     error, strerror(err));
+        Er_raise(alloc, "%s [%s]", error, strerror(err));
     }
     close(udpSock);
 
-    setupRoute(address, prefixLen, logger, eh);
+    Er(setupRoute(address, prefixLen, logger, alloc));
+    Er_ret();
 }
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     if (addrFam == Sockaddr_AF_INET6) {
-        addIp6Address(interfaceName, address, prefixLen, logger, eh);
+        addIp6Address(interfaceName, address, prefixLen, logger, tempAlloc);
     } else if (addrFam == Sockaddr_AF_INET) {
-        addIp4Address(interfaceName, address, prefixLen, logger, eh);
+        addIp4Address(interfaceName, address, prefixLen, logger, tempAlloc);
     } else {
         Assert_true(0);
     }
+    Er_ret();
 }
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh)
+                        struct Allocator* errAlloc))
 {
-    Except_throw(eh, "Not implemented in Illumos");
+    Er_raise(errAlloc, "Not implemented in Illumos");
 }
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh)
+                           struct Allocator* tempAlloc))
 {
-    Except_throw(eh, "NetPlatform_setRoutes is not implemented in this platform.");
-}
+    Er_raise(tempAlloc, "NetPlatform_setRoutes is not implemented in this platform.");
+}

+ 30 - 29
util/platform/netdev/NetPlatform_win32.c

@@ -13,7 +13,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #define _WIN32_WINNT 0x0600
-#include "exception/WinFail.h"
+#include "exception/WinEr.h"
 #include "util/platform/netdev/NetPlatform.h"
 #include "util/Bits.h"
 #include "util/platform/Sockaddr.h"
@@ -53,15 +53,15 @@ typedef NET_LUID IF_LUID, *PIF_LUID;
 #include <ifdef.h>
 #include <iphlpapi.h>
 
-static NET_LUID getLuid(const char* name, struct Except* eh)
+static Er_DEFUN(NET_LUID getLuid(const char* name, struct Allocator* alloc))
 {
     uint16_t ifName[IF_MAX_STRING_SIZE + 1] = {0};
-    WinFail_check(eh,
+    WinEr_check(alloc,
         (!MultiByteToWideChar(CP_ACP, 0, name, strlen(name), ifName, IF_MAX_STRING_SIZE + 1))
     );
     NET_LUID out;
-    WinFail_check(eh, ConvertInterfaceAliasToLuid(ifName, &out));
-    return out;
+    WinEr_check(alloc, ConvertInterfaceAliasToLuid(ifName, &out));
+    Er_ret(out);
 }
 
 static LONG flushAddresses(NET_LUID luid, MIB_UNICASTIPADDRESS_TABLE* table)
@@ -77,24 +77,25 @@ static LONG flushAddresses(NET_LUID luid, MIB_UNICASTIPADDRESS_TABLE* table)
     return out;
 }
 
-void NetPlatform_flushAddresses(const char* deviceName, struct Except* eh)
+Er_DEFUN(void NetPlatform_flushAddresses(const char* deviceName, struct Allocator* alloc))
 {
-    NET_LUID luid = getLuid(deviceName, eh);
+    NET_LUID luid = getLuid(deviceName, alloc);
     MIB_UNICASTIPADDRESS_TABLE* table;
 
-    WinFail_check(eh, GetUnicastIpAddressTable(AF_INET, &table));
+    WinEr_check(alloc, GetUnicastIpAddressTable(AF_INET, &table));
     LONG ret = flushAddresses(luid, table);
     FreeMibTable(table);
     if (ret) {
-        WinFail_fail(eh, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
+        WinEr_fail(alloc, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
     }
 
-    WinFail_check(eh, GetUnicastIpAddressTable(AF_INET6, &table));
+    WinEr_check(alloc, GetUnicastIpAddressTable(AF_INET6, &table));
     ret = flushAddresses(luid, table);
     FreeMibTable(table);
     if (ret) {
-        WinFail_fail(eh, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
+        WinEr_fail(alloc, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
     }
+    Er_ret();
 }
 #include "util/Hex.h"
 #include <stdio.h>
@@ -103,12 +104,12 @@ static void setupRoute(const char* deviceName,
                        const uint8_t* addrBytes,
                        int prefixLen,
                        int addrFam,
-                       struct Except* eh)
+                       struct Allocator* alloc)
 {
     void WINAPI InitializeIpForwardEntry(PMIB_IPFORWARD_ROW2 Row);
 
     MIB_IPFORWARD_ROW2 row = {
-        .InterfaceLuid = getLuid(deviceName, eh),
+        .InterfaceLuid = getLuid(deviceName, alloc),
         .ValidLifetime = WSA_INFINITE,
         .PreferredLifetime = WSA_INFINITE,
         .Metric = 0xffffffff,
@@ -156,16 +157,16 @@ static void setupRoute(const char* deviceName,
 //    Hex_encode(buff, sizeof(buff), (uint8_t*) &row, sizeof(row));
 //    printf("%s %d<\n", buff, row.SitePrefixLength);
 
-    WinFail_check(eh, CreateIpForwardEntry2(&row));
+    WinEr_check(alloc, CreateIpForwardEntry2(&row));
+    Er_ret();
 }
 
-void NetPlatform_addAddress(const char* interfaceName,
+Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
                             const uint8_t* address,
                             int prefixLen,
                             int addrFam,
                             struct Log* logger,
-                            struct Allocator* tempAlloc,
-                            struct Except* eh)
+                            struct Allocator* tempAlloc))
 {
     MIB_UNICASTIPADDRESS_ROW ipRow = {
         .PrefixOrigin = IpPrefixOriginUnchanged,
@@ -188,15 +189,15 @@ void NetPlatform_addAddress(const char* interfaceName,
 
     ipRow.OnLinkPrefixLength = prefixLen;
 
-    WinFail_check(eh, CreateUnicastIpAddressEntry(&ipRow));
-return;
-    setupRoute(interfaceName, address, prefixLen, addrFam, eh);
+    WinEr_check(CreateUnicastIpAddressEntry(&ipRow));
+    //setupRoute(interfaceName, address, prefixLen, addrFam, eh);
+    Er_ret();
 }
 
-void NetPlatform_setMTU(const char* interfaceName,
+Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
                         uint32_t mtu,
                         struct Log* logger,
-                        struct Except* eh)
+                        struct Allocator* errAlloc))
 {
 
     // I looked all through the Windows API and setting the MTU is beyond me.
@@ -225,22 +226,22 @@ void NetPlatform_setMTU(const char* interfaceName,
     Log_debug(logger, "Going to run command: %s", buffer);
 
     // Make the netsh call, and die if it returns the wrong thing.
-    WinFail_check(eh, system(buffer));
+    WinEr_check(eh, system(buffer));
 
     // We should also configure the MTU for ipv4 (IpTunnel) case
     const char* format1 = ("netsh interface ipv4 set subinterface "
         "\"%s\" mtu=%d");
     snprintf(buffer, totalSize, format1, interfaceName, mtu);
     Log_debug(logger, "Going to run command: %s", buffer);
-    WinFail_check(eh, system(buffer));
+    WinEr_check(eh, system(buffer));
+    Er_ret();
 }
 
-void NetPlatform_setRoutes(const char* ifName,
+Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
                            struct Sockaddr** prefixSet,
                            int prefixCount,
                            struct Log* logger,
-                           struct Allocator* tempAlloc,
-                           struct Except* eh)
+                           struct Allocator* tempAlloc))
 {
-    Except_throw(eh, "NetPlatform_setRoutes is not implemented in this platform.");
-}
+    Er_raise(tempAlloc, "NetPlatform_setRoutes is not implemented in this platform.");
+}

+ 1 - 1
util/test/Base10_test.c

@@ -45,7 +45,7 @@ int main()
         Assert_true(msg->length == (int)CString_strlen(buff));
         Assert_true(!Bits_memcmp(msg->bytes, buff, msg->length));
 
-        int64_t read = Base10_read(msg, NULL);
+        int64_t read = Er_assert(Base10_read(msg));
         Assert_true(read == num);
         Assert_true(msg->length == 0);
     }

+ 1 - 1
util/test/Process_test.c

@@ -127,7 +127,7 @@ static Iface_DEFUN receiveMessageChild(struct Message* msg, struct Iface* iface)
 
 static void child(char* name, struct Context* ctx)
 {
-    struct Pipe* pipe = Pipe_named(name, ctx->base, NULL, ctx->log, ctx->alloc);
+    struct Pipe* pipe = Er_assert(Pipe_named(name, ctx->base, ctx->log, ctx->alloc));
     pipe->onConnection = onConnectionChild;
     pipe->userData = ctx;
     ctx->iface.send = receiveMessageChild;

+ 2 - 2
util/test/Seccomp_test.c

@@ -53,7 +53,7 @@ static void onConnectionChild(struct Pipe* pipe, int status)
 {
     struct ChildCtx* child = Identity_check((struct ChildCtx*) pipe->userData);
 
-    Seccomp_dropPermissions(child->alloc, child->log, NULL);
+    Er_assert(Seccomp_dropPermissions(child->alloc, child->log));
     Assert_true(Seccomp_isWorking());
 
     struct Message* ok = Message_new(0, 512, child->alloc);
@@ -84,7 +84,7 @@ static int child(char* pipeName, struct Allocator* alloc, struct Log* logger)
     ctx->base = EventBase_new(alloc);
     ctx->alloc = alloc;
     ctx->log = logger;
-    ctx->pipe = Pipe_named(pipeName, ctx->base, NULL, logger, alloc);
+    ctx->pipe = Er_assert(Pipe_named(pipeName, ctx->base, logger, alloc));
     ctx->pipe->onConnection = onConnectionChild;
     ctx->pipe->userData = ctx;
     Identity_set(ctx);

+ 84 - 3
wire/Message.h

@@ -15,14 +15,15 @@
 #ifndef Message_H
 #define Message_H
 
+#include "exception/Er.h"
 #include "exception/Except.h"
-#include <stdint.h>
-
 #include "memory/Allocator.h"
 #include "util/Bits.h"
 #include "util/Endian.h"
 #include "util/UniqueName.h"
 
+#include <stdint.h>
+
 struct Message
 {
     /** The length of the message. */
@@ -151,6 +152,23 @@ static inline int Message_shift(struct Message* toShift, int32_t amount, struct
     return 1;
 }
 
+static inline Er_DEFUN(void Message_eshift(struct Message* toShift, int32_t amount))
+{
+    if (amount > 0 && toShift->padding < amount) {
+        Er_raise(toShift->alloc, "buffer overflow adding %d to length %d",
+            amount, toShift->length);
+    } else if (toShift->length < (-amount)) {
+        Er_raise(toShift->alloc, "buffer underflow");
+    }
+
+    toShift->length += amount;
+    toShift->capacity += amount;
+    toShift->bytes -= amount;
+    toShift->padding -= amount;
+
+    Er_ret();
+}
+
 static inline void Message_reset(struct Message* toShift)
 {
     Assert_true(toShift->length <= toShift->capacity);
@@ -158,6 +176,19 @@ static inline void Message_reset(struct Message* toShift)
     Message_shift(toShift, -toShift->length, NULL);
 }
 
+static inline Er_DEFUN(void Message_epush(struct Message* restrict msg,
+                                          const void* restrict object,
+                                          size_t size))
+{
+    Er(Message_eshift(msg, (int)size));
+    if (object) {
+        Bits_memcpy(msg->bytes, object, size);
+    } else {
+        Bits_memset(msg->bytes, 0x00, size);
+    }
+    Er_ret();
+}
+
 static inline void Message_push(struct Message* restrict msg,
                                 const void* restrict object,
                                 size_t size,
@@ -182,11 +213,28 @@ static inline void Message_pop(struct Message* restrict msg,
     }
 }
 
+static inline Er_DEFUN(void Message_epop(struct Message* restrict msg,
+                                         void* restrict object,
+                                         size_t size))
+{
+    Er(Message_eshift(msg, -(int)size));
+    if (object) {
+        Bits_memcpy(object, &msg->bytes[-((int)size)], size);
+    }
+    Er_ret();
+}
+
 #define Message_pushH(size) \
     static inline void Message_push ## size ## h                                          \
         (struct Message* msg, uint ## size ## _t dat, struct Except* eh)                  \
     {                                                                                     \
         Message_push(msg, &dat, (size)/8, eh);                                            \
+    } \
+    static inline Er_DEFUN(void Message_epush ## size ## h                                \
+        (struct Message* msg, uint ## size ## _t dat))                                    \
+    {                                                                                     \
+        Er(Message_epush(msg, &dat, (size)/8));                                           \
+        Er_ret(); \
     }
 #define Message_popH(size) \
     static inline uint ## size ## _t Message_pop ## size ## h \
@@ -195,6 +243,12 @@ static inline void Message_pop(struct Message* restrict msg,
         uint ## size ## _t out;                                                                   \
         Message_pop(msg, &out, (size)/8, eh);                                                     \
         return out;                                                                               \
+    } \
+    static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## h(struct Message* msg))     \
+    {                                                                                             \
+        uint ## size ## _t out;                                                                   \
+        Er(Message_epop(msg, &out, (size)/8));                                                    \
+        Er_ret(out); \
     }
 
 #define Message_pushBE(size) \
@@ -213,12 +267,24 @@ static inline void Message_pop(struct Message* restrict msg,
     static inline uint ## size ## _t Message_pop ## size (struct Message* msg, struct Except* eh) \
     {                                                                                             \
         return Endian_bigEndianToHost ## size (Message_pop ## size ## h(msg, eh));                \
+    } \
+    static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## be(struct Message* msg)) \
+    {                                                                                             \
+        uint ## size ## _t out = Er(Message_epop ## size ## h(msg));                              \
+        uint ## size ## _t out1 = Endian_bigEndianToHost ## size (out);                           \
+        Er_ret(out1);                                                                             \
     }
 #define Message_popLE(size) \
     static inline uint ## size ## _t Message_pop ## size ## le \
         (struct Message* msg, struct Except* eh) \
     {                                                                                             \
         return Endian_littleEndianToHost ## size (Message_pop ## size ## h(msg, eh));             \
+    } \
+    static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## le(struct Message* msg)) \
+    {                                                                                             \
+        uint ## size ## _t out = Er(Message_epop ## size ## h(msg));                              \
+        uint ## size ## _t out1 = Endian_littleEndianToHost ## size (out);                        \
+        Er_ret(out1);                                                                             \
     }
 
 #define Message_pushPop(size) \
@@ -226,9 +292,24 @@ static inline void Message_pop(struct Message* restrict msg,
     Message_pushBE(size) Message_popBE(size) \
     Message_pushLE(size) Message_popLE(size)
 
-Message_pushPop(8)
+Message_pushH(8)
+Message_popH(8)
+#define Message_push8 Message_push8h
+#define Message_pop8 Message_pop8h
+
+#define Message_epush8 Message_epush8h
+#define Message_epop8 Message_epop8h
+
 Message_pushPop(16)
 Message_pushPop(32)
 Message_pushPop(64)
 
+#define Message_epush16le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian16(x))
+#define Message_epush32le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian32(x))
+#define Message_epush64le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian64(x))
+
+#define Message_epush16be(msg, x) Message_epush16h(msg, Endian_hostToBigEndian16(x))
+#define Message_epush32be(msg, x) Message_epush32h(msg, Endian_hostToBigEndian32(x))
+#define Message_epush64be(msg, x) Message_epush64h(msg, Endian_hostToBigEndian64(x))
+
 #endif