Move TRP messaging to tr_msg.c. Fix old bug.
authorJennifer Richards <jennifer@painless-security.com>
Fri, 17 Jun 2016 01:49:26 +0000 (21:49 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Fri, 17 Jun 2016 01:49:26 +0000 (21:49 -0400)
* Move TRP message-related code to tr_msg.c
* Change names/code to match existing conventions
* Add constructor/destructor for TID_RESP struct
* Free sub-structures when freeing TR_MSG struct
* Add msgtst to Makefile.am

Makefile.am
common/tr_msg.c
include/tr_msg.h
include/trp_internal.h
include/trust_router/tid.h
include/trust_router/trp.h [new file with mode: 0644]
tid/tid_resp.c
trp/msgtst.c
trp/trp_msg.c

index 35d4815..eadc2df 100644 (file)
@@ -1,6 +1,6 @@
 DISTCHECK_CONFIGURE_FLAGS = \
        --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
-bin_PROGRAMS= tr/trust_router tr/trpc tid/example/tidc tid/example/tids common/dh_test/tr_dh_test
+bin_PROGRAMS= tr/trust_router tr/trpc tid/example/tidc tid/example/tids common/dh_test/tr_dh_test trp/msgtst
 AM_CPPFLAGS=-I$(srcdir)/include $(GLIB_CFLAGS)
 AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses $(GLIB_CFLAGS)
 SUBDIRS = gsscon 
@@ -41,6 +41,21 @@ tr/tr_trp.c
 
 tr_trpc_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
 
+trp_msgtst_SOURCES = trp/msgtst.c \
+trp/trp_msg.c \
+tid/tid_req.c \
+tid/tid_resp.c \
+common/tr_name.c \
+common/tr_msg.c \
+common/tr_idp.c \
+common/tr_comm.c \
+common/tr_filter.c \
+common/tr_rp.c \
+common/tr_config.c \
+common/tr_debug.c 
+
+trp_msgtst_LDADD = libtr_tid.la $(GLIB_LIBS)
+
 tid_example_tidc_SOURCES = tid/example/tidc_main.c 
 
 tid_example_tidc_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
index f68c5d1..0d55ebe 100644 (file)
 #include <tr_msg.h>
 #include <trust_router/tr_name.h>
 #include <tid_internal.h>
+#include <trp_internal.h>
 #include <trust_router/tr_constraint.h>
 #include <tr_debug.h>
 
+/* JSON helpers */
+/* Read attribute attr from msg as an integer. Returns nonzero on error. */
+static int tr_msg_get_json_integer(json_t *jmsg, const char *attr, int *dest)
+{
+  json_t *obj;
+
+  obj=json_object_get(jmsg, attr);
+  if (obj == NULL) {
+    return -1;
+  }
+  /* check type */
+  if (!json_is_integer(obj)) {
+    return -1;
+  }
+
+  (*dest)=json_integer_value(obj);
+  return 0;
+}
+
+/* Read attribute attr from msg as a string. Copies string into mem_ctx context so jmsg can
+ * be destroyed safely. Returns nonzero on error. */
+static int tr_msg_get_json_string(json_t *jmsg, const char *attr, char **dest, TALLOC_CTX *mem_ctx)
+{
+  json_t *obj;
+
+  obj=json_object_get(jmsg, attr);
+  if (obj == NULL)
+    return -1;
+
+  /* check type */
+  if (!json_is_string(obj))
+    return -1;
+
+  *dest=talloc_strdup(mem_ctx, json_string_value(obj));
+  if (*dest==NULL)
+    return -1;
+
+  return 0;
+}
+
 enum msg_type tr_msg_get_msg_type(TR_MSG *msg) 
 {
   return msg->msg_type;
@@ -83,6 +124,32 @@ void tr_msg_set_resp(TR_MSG *msg, TID_RESP *resp)
   msg->msg_type = TID_RESPONSE;
 }
 
+TRP_UPD *tr_msg_get_trp_upd(TR_MSG *msg)
+{
+  if (msg->msg_type == TRP_UPDATE)
+    return (TRP_UPD *)msg->msg_rep;
+  return NULL;
+}
+
+void tr_msg_set_trp_upd(TR_MSG *msg, TRP_UPD *update)
+{
+  msg->msg_rep=update;
+  msg->msg_type=TRP_UPDATE;
+}
+
+TRP_REQ *tr_msg_get_trp_req(TR_MSG *msg)
+{
+  if (msg->msg_type == TRP_REQUEST)
+    return (TRP_REQ *)msg->msg_rep;
+  return NULL;
+}
+
+void tr_msg_set_trp_req(TR_MSG *msg, TRP_REQ *req)
+{
+  msg->msg_rep=req;
+  msg->msg_type=TRP_REQUEST;
+}
+
 static json_t *tr_msg_encode_dh(DH *dh)
 {
   json_t *jdh = NULL;
@@ -411,7 +478,7 @@ static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
   json_t *jservers = NULL;
   json_t *jerr_msg = NULL;
 
-  if (!(tresp = talloc_zero(NULL, TID_RESP))) {
+  if (!(tresp=tid_resp_new(NULL))) {
     tr_crit("tr_msg_decode_tidresp(): Error allocating TID_RESP structure.");
     return NULL;
   }
@@ -465,6 +532,331 @@ static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
   return tresp;
 }
 
+
+/* Information records for TRP update msg 
+ * requires that jrec already be allocated */
+static TRP_RC tr_msg_encode_inforec_route(json_t *jrec, TRP_INFOREC_DATA rec_data)
+{
+  TRP_INFOREC_ROUTE *route=rec_data.route;
+  json_t *jstr=NULL;
+  json_t *jint=NULL;
+  char *s=NULL;
+
+  if (route==NULL)
+    return TRP_BADTYPE;
+
+  s=tr_name_strdup(route->comm);
+  if (s==NULL)
+    return TRP_NOMEM;
+  jstr=json_string(s);
+  free(s);s=NULL;
+  if(jstr==NULL)
+    return TRP_ERROR;
+  json_object_set_new(jrec, "community", jstr);
+
+  s=tr_name_strdup(route->realm);
+  if (s==NULL)
+    return TRP_NOMEM;
+  jstr=json_string(s);
+  free(s);s=NULL;
+  if(jstr==NULL)
+    return TRP_ERROR;
+  json_object_set_new(jrec, "realm", jstr);
+
+  s=tr_name_strdup(route->trust_router);
+  if (s==NULL)
+    return TRP_NOMEM;
+  jstr=json_string(s);
+  free(s);s=NULL;
+  if(jstr==NULL)
+    return TRP_ERROR;
+  json_object_set_new(jrec, "trust_router", jstr);
+
+  jint=json_integer(route->metric);
+  if(jint==NULL)
+    return TRP_ERROR;
+  json_object_set_new(jrec, "metric", jint);
+
+  jint=json_integer(route->interval);
+  if(jint==NULL)
+    return TRP_ERROR;
+  json_object_set_new(jrec, "interval", jint);
+
+  return TRP_SUCCESS;
+}
+
+static json_t *tr_msg_encode_inforec(TRP_INFOREC *rec)
+{
+  json_t *jrec=NULL;
+  json_t *jstr=NULL;
+
+  if ((rec==NULL) || (rec->type==TRP_INFOREC_TYPE_UNKNOWN))
+    return NULL;
+
+  jrec=json_object();
+  if (jrec==NULL)
+    return NULL;
+
+  jstr=json_string(trp_inforec_type_to_string(rec->type));
+  if (jstr==NULL) {
+    json_decref(jrec);
+    return NULL;
+  }
+  json_object_set_new(jrec, "record_type", jstr);
+
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (TRP_SUCCESS!=tr_msg_encode_inforec_route(jrec, rec->data)) {
+      json_decref(jrec);
+      return NULL;
+    }
+    break;
+  default:
+    json_decref(jrec);
+    return NULL;
+  }
+  return jrec;
+}
+
+/* decode a single record */
+static TRP_INFOREC *tr_msg_decode_trp_inforec(TALLOC_CTX *mem_ctx, json_t *jrecord)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TRP_INFOREC_TYPE rectype;
+  TRP_INFOREC *rec=NULL;
+  TRP_RC rc=TRP_ERROR;
+  char *s=NULL;
+  int num=0;
+  
+  if (0!=tr_msg_get_json_string(jrecord, "record_type", &s, tmp_ctx))
+    goto cleanup;
+
+  rectype=trp_inforec_type_from_string(s);
+  talloc_free(s); s=NULL;
+
+  rec=trp_inforec_new(tmp_ctx, rectype);
+  if (rec==NULL) {
+    rc=TRP_NOMEM;
+    goto cleanup;
+  }
+
+  /* We only support route_info records for now*/
+  if (rec->type!=TRP_INFOREC_TYPE_ROUTE) {
+    rc=TRP_UNSUPPORTED;
+    goto cleanup;
+  }
+
+  tr_debug("tr_msg_decode_trp_inforec: '%s' record found.", trp_inforec_type_to_string(rec->type));
+
+  rc=tr_msg_get_json_string(jrecord, "community", &s, tmp_ctx);
+  if (rc != TRP_SUCCESS)
+    goto cleanup;
+  if (TRP_SUCCESS!=trp_inforec_set_comm(rec, tr_new_name(s)))
+    goto cleanup;
+  talloc_free(s); s=NULL;
+
+  rc=tr_msg_get_json_string(jrecord, "realm", &s, tmp_ctx);
+  if (rc != TRP_SUCCESS)
+    goto cleanup;
+  if (TRP_SUCCESS!=trp_inforec_set_realm(rec, tr_new_name(s))) /* assumes route_info */
+    goto cleanup;
+  talloc_free(s); s=NULL;
+
+  rc=tr_msg_get_json_string(jrecord, "trust_router", &s, tmp_ctx);
+  if (rc != TRP_SUCCESS)
+    goto cleanup;
+  if (TRP_SUCCESS!=trp_inforec_set_trust_router(rec, tr_new_name(s))) /* assumes route_info */
+    goto cleanup;
+  talloc_free(s); s=NULL;
+
+  rc=tr_msg_get_json_integer(jrecord, "metric", &num);
+  if ((rc != TRP_SUCCESS) || (TRP_SUCCESS!=trp_inforec_set_metric(rec,num)))
+    goto cleanup;
+
+  rc=tr_msg_get_json_integer(jrecord, "interval", &num);
+  if ((rc != TRP_SUCCESS) || (TRP_SUCCESS!=trp_inforec_set_interval(rec,num)))
+    goto cleanup;
+
+  talloc_steal(mem_ctx, rec);
+  rc=TRP_SUCCESS;
+
+cleanup:
+  if (rc != TRP_SUCCESS) {
+    trp_inforec_free(rec);
+    rec=NULL;
+  }
+  talloc_free(tmp_ctx);
+  return rec;
+}
+
+/* TRP update msg */
+static json_t *tr_msg_encode_trp_upd(TRP_UPD *update)
+{
+  json_t *jupdate=NULL;
+  json_t *jrecords=NULL;
+  json_t *jrec=NULL;
+  TRP_INFOREC *rec;
+
+  if (update==NULL)
+    return NULL;
+
+  jupdate=json_object();
+  if (jupdate==NULL)
+    return NULL;
+
+  jrecords=json_array();
+  if (jrecords==NULL) {
+    json_decref(jupdate);
+    return NULL;
+  }
+  json_object_set_new(jupdate, "records", jrecords); /* jrecords now a "borrowed" reference */
+  for (rec=update->records; rec!=NULL; rec=rec->next) {
+    jrec=tr_msg_encode_inforec(rec);
+    if (jrec==NULL) {
+      json_decref(jupdate); /* also decs jrecords and any elements */
+      return NULL;
+    }
+    if (0!=json_array_append_new(jrecords, jrec)) {
+      json_decref(jupdate); /* also decs jrecords and any elements */
+      json_decref(jrec); /* this one did not get added so dec explicitly */
+      return NULL;
+    }
+  }
+
+  return jupdate;
+}
+
+/*Creates a linked list of records in the msg->body talloc context.
+ * An error will be returned if any unparseable records are encountered. 
+ */
+static TRP_UPD *tr_msg_decode_trp_upd(TALLOC_CTX *mem_ctx, json_t *jupdate)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  json_t *jrecords=NULL;
+  size_t ii=0;
+  TRP_UPD *update=NULL;
+  TRP_INFOREC *new_rec=NULL;
+  TRP_INFOREC *list_tail=NULL;
+  TRP_RC rc=TRP_ERROR;
+
+  update=trp_upd_new(tmp_ctx);
+  if (update==NULL) {
+    rc=TRP_NOMEM;
+    goto cleanup;
+  }
+
+  jrecords=json_object_get(jupdate, "records");
+  if ((jrecords==NULL) || (!json_is_array(jrecords))) {
+    rc=TRP_NOPARSE;
+    goto cleanup;
+  }
+
+  tr_debug("tr_msg_decode_trp_upd: found %d records", json_array_size(jrecords));
+  /* process the array */
+  for (ii=0; ii<json_array_size(jrecords); ii++) {
+    new_rec=tr_msg_decode_trp_inforec(update, json_array_get(jrecords, ii));
+    if (new_rec==NULL) {
+      rc=TRP_NOPARSE;
+      goto cleanup;
+    }
+
+    if (list_tail==NULL)
+      update->records=new_rec; /* first is a special case */
+    else
+      list_tail->next=new_rec;
+
+    list_tail=new_rec;
+  }
+
+  /* Succeeded. Move new allocations into the correct talloc context */
+  talloc_steal(mem_ctx, update);
+  rc=TRP_SUCCESS;
+
+cleanup:
+  talloc_free(tmp_ctx);
+  if (rc!=TRP_SUCCESS)
+    return NULL;
+  return update;
+}
+
+static json_t *tr_msg_encode_trp_req(TRP_REQ *req)
+{
+  json_t *jbody=NULL;
+  json_t *jstr=NULL;
+  char *s=NULL;
+
+  if (req==NULL)
+    return NULL;
+
+  jbody=json_object();
+  if (jbody==NULL)
+    return NULL;
+
+  s=tr_name_strdup(req->comm); /* ensures null termination */
+  if (s==NULL) {
+    json_decref(jbody);
+    return NULL;
+  }
+  jstr=json_string(s);
+  free(s); s=NULL;
+  if (jstr==NULL) {
+    json_decref(jbody);
+    return NULL;
+  }
+  json_object_set_new(jbody, "community", jstr);
+    
+  s=tr_name_strdup(req->realm); /* ensures null termination */
+  if (s==NULL) {
+    json_decref(jbody);
+    return NULL;
+  }
+  jstr=json_string(s);
+  free(s); s=NULL;
+  if (jstr==NULL) {
+    json_decref(jbody);
+    return NULL;
+  }
+  json_object_set_new(jbody, "realm", jstr);
+
+  return jbody;
+}
+
+static TRP_REQ *tr_msg_decode_trp_req(TALLOC_CTX *mem_ctx, json_t *jreq)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TRP_REQ *req=NULL;
+  char *s=NULL;
+  TRP_RC rc=TRP_ERROR;
+
+  /* check message type and body type for agreement */
+  req=trp_req_new(tmp_ctx);
+  if (req==NULL) {
+    rc=TRP_NOMEM;
+    goto cleanup;
+  }
+
+  rc=tr_msg_get_json_string(jreq, "community", &s, tmp_ctx);
+  if (rc!=TRP_SUCCESS)
+    goto cleanup;
+  req->comm=tr_new_name(s);
+  talloc_free(s); s=NULL;
+
+  rc=tr_msg_get_json_string(jreq, "realm", &s, tmp_ctx);
+  if (rc!=TRP_SUCCESS)
+    goto cleanup;
+  req->realm=tr_new_name(s);
+  talloc_free(s); s=NULL;
+
+  rc=TRP_SUCCESS;
+  talloc_steal(mem_ctx, req);
+
+cleanup:
+  talloc_free(tmp_ctx);
+  if (rc!=TRP_SUCCESS)
+    return NULL;
+  return req;
+}
+
 char *tr_msg_encode(TR_MSG *msg) 
 {
   json_t *jmsg;
@@ -488,7 +880,17 @@ char *tr_msg_encode(TR_MSG *msg)
       json_object_set_new(jmsg, "msg_body", tr_msg_encode_tidresp(tr_msg_get_resp(msg)));
       break;
 
-      /* TBD -- Add TR message types */
+    case TRP_UPDATE:
+      jmsg_type = json_string("trp_update");
+      json_object_set_new(jmsg, "msg_type", jmsg_type);
+      json_object_set_new(jmsg, "msg_body", tr_msg_encode_trp_upd(tr_msg_get_trp_upd(msg)));
+      break;
+
+    case TRP_REQUEST:
+      jmsg_type = json_string("trp_request");
+      json_object_set_new(jmsg, "msg_type", jmsg_type);
+      json_object_set_new(jmsg, "msg_body", tr_msg_encode_trp_req(tr_msg_get_trp_req(msg)));
+      break;
 
     default:
       json_decref(jmsg);
@@ -502,11 +904,11 @@ char *tr_msg_encode(TR_MSG *msg)
 
 TR_MSG *tr_msg_decode(char *jbuf, size_t buflen)
 {
-  TR_MSG *msg;
+  TR_MSG *msg=NULL;
   json_t *jmsg = NULL;
   json_error_t rc;
-  json_t *jtype;
-  json_t *jbody;
+  json_t *jtype=NULL;
+  json_t *jbody=NULL;
   const char *mtype = NULL;
 
   if (NULL == (jmsg = json_loadb(jbuf, buflen, JSON_DISABLE_EOF_CHECK, &rc))) {
@@ -540,6 +942,14 @@ TR_MSG *tr_msg_decode(char *jbuf, size_t buflen)
     msg->msg_type = TID_RESPONSE;
     tr_msg_set_resp(msg, tr_msg_decode_tidresp(jbody));
   }
+  else if (0 == strcmp(mtype, "trp_update")) {
+    msg->msg_type = TRP_UPDATE;
+    tr_msg_set_trp_upd(msg, tr_msg_decode_trp_upd(NULL, jbody)); /* null talloc context for now */
+  }
+  else if (0 == strcmp(mtype, "trp_request")) {
+    msg->msg_type = TRP_UPDATE;
+    tr_msg_set_trp_req(msg, tr_msg_decode_trp_req(NULL, jbody)); /* null talloc context for now */
+  }
   else {
     msg->msg_type = TR_UNKNOWN;
     msg->msg_rep = NULL;
@@ -555,8 +965,24 @@ void tr_msg_free_encoded(char *jmsg)
 
 void tr_msg_free_decoded(TR_MSG *msg)
 {
-  if (msg)
+  if (msg) {
+    switch (msg->msg_type) {
+    case TID_REQUEST:
+      tid_req_free(tr_msg_get_req(msg));
+      break;
+    case TID_RESPONSE:
+      tid_resp_free(tr_msg_get_resp(msg));
+      break;
+    case TRP_UPDATE:
+      trp_upd_free(tr_msg_get_trp_upd(msg));
+      break;
+    case TRP_REQUEST:
+      trp_req_free(tr_msg_get_trp_req(msg));
+    default:
+      break;
+    }
     free (msg);
+  }
 }
 
 
index 4f208e5..0a9096f 100644 (file)
 
 #include <jansson.h>
 #include <trust_router/tid.h>
-
+#include <trust_router/trp.h>
 typedef struct tr_msg TR_MSG;
 
 enum msg_type {
   TR_UNKNOWN = 0,
   TID_REQUEST,
-  TID_RESPONSE
+  TID_RESPONSE,
+  TRP_UPDATE,
+  TRP_REQUEST
 };
 
 /* Union of TR message types to hold message of any type. */
@@ -59,6 +61,11 @@ TID_REQ *tr_msg_get_req(TR_MSG *msg);
 void tr_msg_set_req(TR_MSG *msg, TID_REQ *req);
 TID_RESP *tr_msg_get_resp(TR_MSG *msg);
 void tr_msg_set_resp(TR_MSG *msg, TID_RESP *resp);
+TRP_UPD *tr_msg_get_trp_upd(TR_MSG *msg);
+void tr_msg_set_trp_upd(TR_MSG *msg, TRP_UPD *req);
+TRP_REQ *tr_msg_get_trp_req(TR_MSG *msg);
+void tr_msg_set_trp_req(TR_MSG *msg, TRP_REQ *req);
+
 
 /* Encoders/Decoders */
 char *tr_msg_encode(TR_MSG *msg);
index f167fdc..dab0140 100644 (file)
@@ -5,92 +5,72 @@
 
 #include <gsscon.h>
 #include <trust_router/tr_dh.h>
-
-#define TRP_PORT 12310
-#define TRP_METRIC_INFINITY 0xFFFF
-#define TRP_METRIC_INVALID 0xFFFFFFFF
-#define TRP_INTERVAL_INVALID 0
-
-typedef enum trp_rc {
-  TRP_SUCCESS=0,
-  TRP_ERROR, /* generic error */
-  TRP_NOPARSE, /* parse error */
-  TRP_NOMEM, /* allocation error */
-  TRP_BADTYPE, /* typing error */
-  TRP_UNSUPPORTED, /* unsupported feature */
-} TRP_RC;
-
-/*** Messages ***/
-typedef enum trp_msg_type {
-  TRP_MSG_TYPE_UNKNOWN=0, /* conveniently, JSON parser returns 0 if a non-integer number is specified */
-  TRP_MSG_TYPE_UPDATE,
-  TRP_MSG_TYPE_ROUTE_REQ
-} TRP_MSG_TYPE;
+#include <trust_router/trp.h>
 
 /* info records */
-typedef enum trp_msg_info_type {
-  TRP_MSG_INFO_TYPE_UNKNOWN=0, /* conveniently, JSON parser returns 0 if a non-integer number is specified */
-  TRP_MSG_INFO_TYPE_ROUTE,
-  TRP_MSG_INFO_TYPE_COMMUNITY, /* not yet implemented (2016-06-14) */
-} TRP_MSG_INFO_TYPE;
-
-typedef struct trp_msg {
-  TRP_MSG_TYPE type;
-  void *body;
-} TRP_MSG;
-
-/* update msg record types */
-typedef struct trp_msg_info_rec TRP_MSG_INFO_REC;
-struct trp_msg_info_rec {
-  TRP_MSG_INFO_REC *next;
-  TRP_MSG_INFO_TYPE type;
-  void *data; /* pointer to one of the record types */
-};
-
-typedef struct trp_msg_info_route {
+typedef enum trp_inforec_type {
+  TRP_INFOREC_TYPE_UNKNOWN=0, /* conveniently, JSON parser returns 0 if a non-integer number is specified */
+  TRP_INFOREC_TYPE_ROUTE,
+  TRP_INFOREC_TYPE_COMMUNITY, /* not yet implemented (2016-06-14) */
+} TRP_INFOREC_TYPE;
+
+/* TRP update record types */
+typedef struct trp_inforec_route {
   TR_NAME *comm;
   TR_NAME *realm;
   TR_NAME *trust_router;
   unsigned int metric;
   unsigned int interval;
-} TRP_MSG_INFO_ROUTE;
+} TRP_INFOREC_ROUTE;
 
 /* TODO: define struct trp_msg_info_community */
 
-typedef struct trp_route_update {
-  void *records;
-} TRP_ROUTE_UPDATE;
+typedef union trp_inforec_data {
+  TRP_INFOREC_ROUTE *route;
+  /* TRP_INFOREC_COMM *comm; */
+} TRP_INFOREC_DATA;
 
-typedef struct trp_route_req {
+typedef struct trp_inforec TRP_INFOREC;
+struct trp_inforec {
+  TRP_INFOREC *next;
+  TRP_INFOREC_TYPE type;
+  TRP_INFOREC_DATA data; /* contains pointer to one of the record types */
+};
+
+struct trp_update {
+  TRP_INFOREC *records;
+};
+
+struct trp_req {
   TR_NAME *comm;
   TR_NAME *realm;
-} TRP_ROUTE_REQ;
-
-TRP_MSG_TYPE trp_msg_type_from_string(const char *s);
-const char *trp_msg_type_to_string(TRP_MSG_TYPE msgtype);
-TRP_MSG_INFO_TYPE trp_msg_info_type_from_string(const char *s);
-const char *trp_msg_info_type_to_string(TRP_MSG_INFO_TYPE msgtype);
+};
 
-TRP_MSG *trp_msg_new(TALLOC_CTX *mem_ctx);
-void trp_msg_destroy(TRP_MSG *msg);
-void trp_msg_pprint(TRP_MSG *msg);
-char *trp_encode_msg(TRP_MSG *msg);
+TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s);
+const char *trp_inforec_type_to_string(TRP_INFOREC_TYPE msgtype);
+
+TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx);
+void trp_upd_free(TRP_UPD *update);
+TRP_REQ *trp_req_new(TALLOC_CTX *mem_ctx);
+void trp_req_free(TRP_REQ *req);
+TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type);
+void trp_inforec_free(TRP_INFOREC *rec);
+TR_NAME *trp_inforec_get_comm(TRP_INFOREC *rec);
+TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm);
+TR_NAME *trp_inforec_get_realm(TRP_INFOREC *rec);
+TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm);
+TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec);
+TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router);
+unsigned int trp_inforec_get_metric(TRP_INFOREC *rec);
+TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric);
+unsigned int trp_inforec_get_interval(TRP_INFOREC *rec);
+TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval);
 
-TR_NAME *trp_msg_info_route_get_comm(TRP_MSG_INFO_REC *rec);
-TR_NAME *trp_msg_info_route_get_realm(TRP_MSG_INFO_REC *rec);
-TR_NAME *trp_msg_info_route_get_trust_router(TRP_MSG_INFO_REC *rec);
-unsigned int trp_msg_info_route_get_metric(TRP_MSG_INFO_REC *rec);
-unsigned int trp_msg_info_route_get_interval(TRP_MSG_INFO_REC *rec);
 
 typedef struct trps_instance TRPS_INSTANCE;
 
-/* REMOVE THIS!! --jennifer, 2016-06-13 */
-typedef TRP_MSG TRP_REQ;
-typedef TRP_MSG TRP_RESP;
-
-
-typedef int (TRPS_REQ_FUNC)(TRPS_INSTANCE *, TRP_REQ *, TRP_RESP *, void *);
-typedef void (TRPS_RESP_FUNC)(TRPS_INSTANCE *, TRP_REQ *, TRP_RESP *, void *);
+typedef int (TRPS_REQ_FUNC)();
+typedef void (TRPS_RESP_FUNC)();
 typedef int (trps_auth_func)(gss_name_t client_name, TR_NAME *display_name, void *cookie);
 
 
index 613541f..88c1a38 100644 (file)
@@ -103,6 +103,9 @@ TR_EXPORT TID_REQ *tid_dup_req (TID_REQ *orig_req);
 void TR_EXPORT tid_req_free( TID_REQ *req);
 
 /* Utility functions for TID_RESP structure, in tid/tid_resp.c */
+
+TID_RESP *tid_resp_new(TALLOC_CTX *mem_ctx);
+void tid_resp_free(TID_RESP *resp);
 TR_EXPORT int tid_resp_get_result(TID_RESP *resp);
 void tid_resp_set_result(TID_RESP *resp, int result);
 TR_EXPORT TR_NAME *tid_resp_get_err_msg(TID_RESP *resp);
diff --git a/include/trust_router/trp.h b/include/trust_router/trp.h
new file mode 100644 (file)
index 0000000..e160543
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef TRP_H
+#define TRP_H
+
+#include <talloc.h>
+
+#define TRP_PORT 12310
+#define TRP_METRIC_INFINITY 0xFFFF
+#define TRP_METRIC_INVALID 0xFFFFFFFF
+#define TRP_INTERVAL_INVALID 0
+
+typedef enum trp_rc {
+  TRP_SUCCESS=0,
+  TRP_ERROR, /* generic error */
+  TRP_NOPARSE, /* parse error */
+  TRP_NOMEM, /* allocation error */
+  TRP_BADTYPE, /* typing error */
+  TRP_UNSUPPORTED, /* unsupported feature */
+} TRP_RC;
+
+
+typedef struct trp_update TRP_UPD;
+typedef struct trp_req TRP_REQ;
+
+#endif /* TRP_H */
index 2611b3b..44a866a 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <talloc.h>
 
 #include <tid_internal.h>
 
+TID_RESP *tid_resp_new(TALLOC_CTX *mem_ctx)
+{
+  return talloc(mem_ctx, TID_RESP);
+}
+
+void tid_resp_free(TID_RESP *resp)
+{
+  if (resp)
+    talloc_free(resp);
+}
+
 TR_EXPORT int tid_resp_get_result(TID_RESP *resp)
 {
   return(resp->result);
index 5622e3a..aef0c19 100644 (file)
@@ -1,11 +1,12 @@
 /* Testing trp message encoding / decoding */
 
-/* compiles with: gcc -o msgtst -I../include -I../include/trust_router msgtst.c trp_msg.c $(pkg-config --cflags --libs glib-2.0) ../common/tr_debug.c  ../common/tr_name.c -ltalloc -ljansson */
+/* compiles with: gcc -o msgtst -I../include msgtst.c trp_msg.c $(pkg-config --cflags --libs glib-2.0) ../common/tr_debug.c  ../common/tr_name.c ../common/tr_msg.c -ltalloc -ljansson */
 
 #include <stdio.h>
 #include <talloc.h>
 
-#include <trp_internal.h>
+#include <trust_router/trp.h>
+#include <tr_msg.h>
 #include <tr_debug.h>
 
 #define MAX_MSG_LEN 8192
@@ -16,8 +17,7 @@ int main(int argc, const char *argv[])
   FILE *f;
   char *buf;
   size_t buflen;
-  TRP_RC rc;
-  TRP_MSG *msg;
+  TR_MSG *msg;
   
   if (argc != 2) {
     printf("Usage: %s <input file>\n\n", argv[0]);
@@ -47,21 +47,16 @@ int main(int argc, const char *argv[])
   if (buflen>=MAX_MSG_LEN)
     printf("Warning: file may exceed maximum message length (%d bytes).\n", MAX_MSG_LEN);
 
-  rc=trp_parse_msg(main_ctx, buf, buflen, &msg);
-  printf("trp_parse_msg returned %d\n\n", rc);
+  msg=tr_msg_decode(buf, buflen);
 
-  if (rc==TRP_SUCCESS)
-    trp_msg_print(msg);
+/*  if (rc==TRP_SUCCESS)
+    trp_msg_print(msg);*/
 
   printf("\nEncoding...\n");
 
-  printf("Result: \n%s\n\n", trp_encode_msg(msg));
+  printf("Result: \n%s\n\n", tr_msg_encode(msg));
 
   talloc_report_full(main_ctx, stdout);
 
-  if (rc==TRP_SUCCESS)
-    talloc_free(msg);
-
-  talloc_report_full(main_ctx, stdout);
   return 0;
 }
index 304d7fe..0545fc4 100644 (file)
@@ -1,92 +1,35 @@
 #include <jansson.h>
 #include <talloc.h>
 
-#include <tr_name.h>
+#include <trust_router/tr_name.h>
 #include <trp_internal.h>
 #include <tr_debug.h>
 
 
 /* static prototypes */
-static void *trp_route_update_new(TALLOC_CTX *mem_ctx);
-static json_t *trp_encode_route_update(void *req_in);
-static TRP_RC trp_parse_route_update(TRP_MSG *msg, json_t *jmsg);
-static void trp_route_update_print(void *);
-
-static void *trp_route_req_new(TALLOC_CTX *mem_ctx);
-static json_t *trp_encode_route_req(void *req_in);
-static TRP_RC trp_parse_route_req(TRP_MSG *msg, json_t *jmsg);
-static void trp_route_req_print(void *);
-
-static void *trp_msg_info_route_new(TALLOC_CTX *mem_ctx);
-static TRP_RC trp_encode_info_route(json_t *jrec, void *route_in);
-static TRP_RC trp_parse_info_route(TRP_MSG *msg, json_t *jmsg);
-static void trp_msg_info_route_print(void *);
-
-/* table of string names for TMT_MSG_TYPE codes */
-struct trp_msg_type_entry {
-  const char *name;
-  TRP_MSG_TYPE type;
-  void *(*allocate)(TALLOC_CTX *);
-  json_t *(*encode)(void *);
-  TRP_RC (*parse)(TRP_MSG *, json_t *);
-  void (*print)(void *);
-};
-static struct trp_msg_type_entry trp_msg_type_table[] = {
-  { "update", TRP_MSG_TYPE_UPDATE, trp_route_update_new, trp_encode_route_update, trp_parse_route_update, trp_route_update_print },
-  { "route_req", TRP_MSG_TYPE_ROUTE_REQ, trp_route_req_new, trp_encode_route_req, trp_parse_route_req, trp_route_req_print },
-  { NULL, TRP_MSG_TYPE_UNKNOWN, NULL, NULL, NULL, NULL } /* must be the last entry */
-};
+static void *trp_inforec_route_new(TALLOC_CTX *mem_ctx);
+static void trp_inforec_route_print(TRP_INFOREC_DATA);
+
 
-struct trp_msg_info_type_entry {
+struct trp_inforec_type_entry {
   const char *name;
-  TRP_MSG_INFO_TYPE type;
+  TRP_INFOREC_TYPE type;
   void *(*allocate)(TALLOC_CTX *);
-  TRP_RC (*encode)(json_t *, void *);
-  void (*print)(void *);
+  void (*print)(TRP_INFOREC_DATA);
 };
-static struct trp_msg_info_type_entry trp_msg_info_type_table[] = {
-  { "route_info", TRP_MSG_INFO_TYPE_ROUTE, trp_msg_info_route_new, trp_encode_info_route, trp_msg_info_route_print },
-  { "comm_info", TRP_MSG_INFO_TYPE_COMMUNITY, NULL, NULL, NULL },
-  { NULL, TRP_MSG_INFO_TYPE_UNKNOWN, NULL, NULL, NULL } /* must be the last entry */
+static struct trp_inforec_type_entry trp_inforec_type_table[] = {
+  { "route", TRP_INFOREC_TYPE_ROUTE, trp_inforec_route_new, trp_inforec_route_print },
+  { "comm", TRP_INFOREC_TYPE_COMMUNITY, NULL, NULL },
+  { NULL, TRP_INFOREC_TYPE_UNKNOWN, NULL, NULL } /* must be the last entry */
 };
 
-/* Use talloc's dynamic type checking to verify type.
- * By default, this will cause program abort, but can be overridden
- * via talloc_set_abort_fn() if more graceful handling is needed. */
-static void msg_body_type_check(TRP_MSG_TYPE msgtype, void *p)
-{
-  switch (msgtype) {
-  case TRP_MSG_TYPE_UPDATE:
-    talloc_get_type_abort(p, TRP_ROUTE_UPDATE);
-    break;
-
-  case TRP_MSG_TYPE_ROUTE_REQ:
-    talloc_get_type_abort(p, TRP_ROUTE_REQ);
-    break;
 
-  default:
-    break;
-  }
-}
-
-/* look up an entry in the trp_msg_type_table */
-static struct trp_msg_type_entry *get_trp_msg_type_entry(TRP_MSG_TYPE msgtype)
+/* look up an entry in the trp_inforec_type_table */
+static struct trp_inforec_type_entry *get_trp_inforec_type_entry(TRP_INFOREC_TYPE msgtype)
 {
-  struct trp_msg_type_entry *entry=trp_msg_type_table;
+  struct trp_inforec_type_entry *entry=trp_inforec_type_table;
 
-  while ((entry->type != TRP_MSG_TYPE_UNKNOWN)
-        && (entry->type != msgtype)) {
-    entry ++;
-  }
-  return entry;
-}
-
-/* look up an entry in the trp_msg_info_type_table */
-static struct trp_msg_info_type_entry *get_trp_msg_info_type_entry(TRP_MSG_INFO_TYPE msgtype)
-{
-  struct trp_msg_info_type_entry *entry=trp_msg_info_type_table;
-
-  while ((entry->type != TRP_MSG_INFO_TYPE_UNKNOWN)
+  while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
         && (entry->type != msgtype)) {
     entry ++;
   }
@@ -94,11 +37,11 @@ static struct trp_msg_info_type_entry *get_trp_msg_info_type_entry(TRP_MSG_INFO_
 }
 
 /* translate strings to codes */
-TRP_MSG_TYPE trp_msg_type_from_string(const char *s)
+TRP_INFOREC_TYPE trp_inforec_type_from_string(const char *s)
 {
-  struct trp_msg_type_entry *entry=trp_msg_type_table;
+  struct trp_inforec_type_entry *entry=trp_inforec_type_table;
 
-  while ((entry->type != TRP_MSG_TYPE_UNKNOWN)
+  while ((entry->type != TRP_INFOREC_TYPE_UNKNOWN)
         && (strcmp(s, entry->name)!=0)) {
     entry++;
   }
@@ -106,121 +49,41 @@ TRP_MSG_TYPE trp_msg_type_from_string(const char *s)
 }
 /* translate codes to strings (do not need to be freed) 
  * Returns NULL on an unknown code */
-const char *trp_msg_type_to_string(TRP_MSG_TYPE msgtype)
+const char *trp_inforec_type_to_string(TRP_INFOREC_TYPE msgtype)
 {
-  struct trp_msg_type_entry *entry=get_trp_msg_type_entry(msgtype);
+  struct trp_inforec_type_entry *entry=get_trp_inforec_type_entry(msgtype);
   return entry->name;
 }
 
-/* translate strings to codes */
-TRP_MSG_INFO_TYPE trp_msg_info_type_from_string(const char *s)
-{
-  struct trp_msg_info_type_entry *entry=trp_msg_info_type_table;
-
-  while ((entry->type != TRP_MSG_INFO_TYPE_UNKNOWN)
-        && (strcmp(s, entry->name)!=0)) {
-    entry++;
-  }
-  return entry->type;
-}
-/* translate codes to strings (do not need to be freed) 
- * Returns NULL on an unknown code */
-const char *trp_msg_info_type_to_string(TRP_MSG_INFO_TYPE msgtype)
-{
-  struct trp_msg_info_type_entry *entry=get_trp_msg_info_type_entry(msgtype);
-  return entry->name;
-}
-
-
-TRP_MSG *trp_msg_new(TALLOC_CTX *mem_ctx)
-{
-  TRP_MSG *new_msg=talloc(mem_ctx, TRP_MSG);
-
-  if (new_msg != NULL) {
-    new_msg->type=TRP_MSG_INFO_TYPE_UNKNOWN;
-    new_msg->body=NULL;
-  }
-  return new_msg;
-}
-
-void trp_msg_destroy(TRP_MSG *msg)
-{
-  if (msg)
-    talloc_free(msg);
-}
-
-
-/* JSON helpers */
-/* Read attribute attr from msg as an integer */
-static TRP_RC trp_get_json_integer(json_t *jmsg, const char *attr, int *dest)
-{
-  json_error_t err;
-  json_t *obj;
-
-  obj=json_object_get(jmsg, attr);
-  if (obj == NULL) {
-    return TRP_NOPARSE;
-  }
-  /* check type */
-  if (!json_is_integer(obj)) {
-    return TRP_BADTYPE;
-  }
-
-  (*dest)=json_integer_value(obj);
-  return TRP_SUCCESS;
-}
-
-/* Read attribute attr from msg as a string. Copies string into mem_ctx context so jmsg can
- * be destroyed safely. */
-static TRP_RC trp_get_json_string(json_t *jmsg, const char *attr, char **dest, TALLOC_CTX *mem_ctx)
-{
-  json_error_t err;
-  json_t *obj;
-
-  obj=json_object_get(jmsg, attr);
-  if (obj == NULL)
-    return TRP_NOPARSE;
-
-  /* check type */
-  if (!json_is_string(obj))
-    return TRP_BADTYPE;
-
-  *dest=talloc_strdup(mem_ctx, json_string_value(obj));
-  if (*dest==NULL)
-    return TRP_NOMEM;
-
-  return TRP_SUCCESS;
-}
-
 
 /* called by talloc when destroying an update message body */
-static int trp_msg_info_route_destructor(void *object)
+static int trp_inforec_route_destructor(void *object)
 {
-  TRP_MSG_INFO_ROUTE *body=talloc_get_type_abort(object, TRP_MSG_INFO_ROUTE);
+  TRP_INFOREC_ROUTE *body=talloc_get_type_abort(object, TRP_INFOREC_ROUTE);
   
   /* clean up TR_NAME data, which are not managed by talloc */
   if (body->comm != NULL) {
     tr_free_name(body->comm);
     body->comm=NULL;
-    tr_debug("trp_msg_info_route_destructor: freed community");
+    tr_debug("trp_inforec_route_destructor: freed community");
   }
   if (body->realm != NULL) {
     tr_free_name(body->realm);
     body->realm=NULL;
-    tr_debug("trp_msg_info_route_destructor: freed realm");
+    tr_debug("trp_inforec_route_destructor: freed realm");
   }
   if (body->trust_router != NULL) {
     tr_free_name(body->trust_router);
     body->trust_router=NULL;
-    tr_debug("trp_msg_info_route_destructor: freed trust_router");
+    tr_debug("trp_inforec_route_destructor: freed trust_router");
   }
 
   return 0;
 }
 
-static void *trp_msg_info_route_new(TALLOC_CTX *mem_ctx)
+static void *trp_inforec_route_new(TALLOC_CTX *mem_ctx)
 {
-  TRP_MSG_INFO_ROUTE *new_rec=talloc(mem_ctx, TRP_MSG_INFO_ROUTE);
+  TRP_INFOREC_ROUTE *new_rec=talloc(mem_ctx, TRP_INFOREC_ROUTE);
 
   if (new_rec != NULL) {
     new_rec->comm=NULL;
@@ -228,720 +91,256 @@ static void *trp_msg_info_route_new(TALLOC_CTX *mem_ctx)
     new_rec->trust_router=NULL;
     new_rec->metric=TRP_METRIC_INFINITY;
     new_rec->interval=0;
-    talloc_set_destructor((void *)new_rec, trp_msg_info_route_destructor);
+    talloc_set_destructor((void *)new_rec, trp_inforec_route_destructor);
   }
   return new_rec;
 }
 
-TR_NAME *trp_msg_info_route_get_comm(TRP_MSG_INFO_REC *rec)
+TR_NAME *trp_inforec_get_comm(TRP_INFOREC *rec)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL))
-    return route->comm;
-  else
-    return NULL;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL)
+      return rec->data.route->comm;
+    break;
+  default:
+    break;
+  }
+  return NULL;
 }
 
-TRP_RC trp_msg_info_route_set_comm(TRP_MSG_INFO_REC *rec, TR_NAME *comm)
+TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL)) {
-    route->comm=comm;
-    return TRP_SUCCESS;
-  } else
-    return TRP_BADTYPE;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL) {
+      rec->data.route->comm=comm;
+      return TRP_SUCCESS;
+    }
+    break;
+  default:
+    break;
+  }
+  return TRP_ERROR;
 }
 
-TR_NAME *trp_msg_info_route_get_realm(TRP_MSG_INFO_REC *rec)
+TR_NAME *trp_inforec_get_realm(TRP_INFOREC *rec)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL))
-    return route->realm;
-  else
-    return NULL;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL)
+      return rec->data.route->realm;
+    break;
+  default:
+    break;
+  }
+  return NULL;
 }
 
-TRP_RC trp_msg_info_route_set_realm(TRP_MSG_INFO_REC *rec, TR_NAME *realm)
+TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL)) {
-    route->realm=realm;
-    return TRP_SUCCESS;
-  } else
-    return TRP_BADTYPE;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL) {
+      rec->data.route->realm=realm;
+      return TRP_SUCCESS;
+    } 
+    break;
+  default:
+    break;
+  }
+  return TRP_ERROR;
 }
 
-TR_NAME *trp_msg_info_route_get_trust_router(TRP_MSG_INFO_REC *rec)
+TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL))
-    return route->trust_router;
-  else
-    return NULL;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL)
+      return rec->data.route->trust_router;
+    break;
+  default:
+    break;
+  }
+  return NULL;
 }
 
-TRP_RC trp_msg_info_route_set_trust_router(TRP_MSG_INFO_REC *rec, TR_NAME *trust_router)
+TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL)) {
-    route->trust_router=trust_router;
-    return TRP_SUCCESS;
-  } else
-    return TRP_BADTYPE;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL) {
+      rec->data.route->trust_router=trust_router;
+      return TRP_SUCCESS;
+    }
+    break;
+  default:
+    break;
+  }
+  return TRP_ERROR;
+}
+
+unsigned int trp_inforec_get_metric(TRP_INFOREC *rec)
+{
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL)
+      return rec->data.route->metric;
+    break;
+  default:
+    break;
+  }
+  return TRP_METRIC_INVALID;
 }
 
-unsigned int trp_msg_info_route_get_metric(TRP_MSG_INFO_REC *rec)
+TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL))
-    return route->metric;
-  else
-    return TRP_METRIC_INVALID;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL) {
+      rec->data.route->metric=metric;
+      return TRP_SUCCESS;
+    }
+    break;
+  default:
+    break;
+  }
+  return TRP_ERROR;
 }
 
-TRP_RC trp_msg_info_route_set_metric(TRP_MSG_INFO_REC *rec, unsigned int metric)
+unsigned int trp_inforec_get_interval(TRP_INFOREC *rec)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL)) {
-    route->metric=metric;
-    return TRP_SUCCESS;
-  } else
-    return TRP_BADTYPE;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL)
+      return rec->data.route->interval;
+    break;
+  default:
+    break;
+  }
+  return TRP_INTERVAL_INVALID;
 }
 
-unsigned int trp_msg_info_route_get_interval(TRP_MSG_INFO_REC *rec)
+TRP_RC trp_inforec_set_interval(TRP_INFOREC *rec, unsigned int interval)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL))
-    return route->interval;
-  else
-    return TRP_INTERVAL_INVALID;
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    if (rec->data.route!=NULL) {
+      rec->data.route->interval=interval;
+      return TRP_SUCCESS;
+  default:
+    break;
+    }
+    break;
+  }
+  return TRP_ERROR;
 }
 
-TRP_RC trp_msg_info_route_set_interval(TRP_MSG_INFO_REC *rec, unsigned int interval)
+/* for internal use only; must set rec->type before calling this */
+static TRP_RC trp_inforec_set_data(TRP_INFOREC *rec, void *data)
 {
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(rec->data, TRP_MSG_INFO_ROUTE);
-  if ((rec->type==TRP_MSG_INFO_TYPE_ROUTE) && (route!=NULL)) {
-    route->interval=interval;
-    return TRP_SUCCESS;
-  } else
+  if (data==NULL)
+    return TRP_ERROR;
+
+  switch (rec->type) {
+  case TRP_INFOREC_TYPE_ROUTE:
+    rec->data.route=talloc_get_type(data, TRP_INFOREC_ROUTE);
+    break;
+  default:
     return TRP_BADTYPE;
+  }
+  return TRP_SUCCESS;
 }
 
 /* generic record type */
-static void *trp_msg_info_rec_new(TALLOC_CTX *mem_ctx, TRP_MSG_INFO_TYPE type)
+TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type)
 {
-  TRP_MSG_INFO_REC *new_rec=talloc(mem_ctx, TRP_MSG_INFO_REC);
-  struct trp_msg_info_type_entry *dtype=get_trp_msg_info_type_entry(type);
+  TRP_INFOREC *new_rec=talloc(mem_ctx, TRP_INFOREC);
+  struct trp_inforec_type_entry *dtype=get_trp_inforec_type_entry(type);
 
-  if ((new_rec != NULL) && (dtype->type != TRP_MSG_INFO_TYPE_UNKNOWN)) {
+  if ((new_rec != NULL) && (dtype->type != TRP_INFOREC_TYPE_UNKNOWN)) {
     new_rec->next=NULL;
     new_rec->type=type;
-    if (dtype->allocate!=NULL)
-      new_rec->data=dtype->allocate(new_rec);
-    if (new_rec->data==NULL) {
-      /* dtype->allocate() failed or did not exist */
-      talloc_free(new_rec); new_rec=NULL;
+    if (dtype->allocate!=NULL) {
+      if (TRP_SUCCESS!=trp_inforec_set_data(new_rec, dtype->allocate(new_rec))) {
+        talloc_free(new_rec);
+        new_rec=NULL;
+      }
     }
   }
   return new_rec;
 }
 
-/* parse a single record */
-static TRP_RC trp_parse_update_record(TALLOC_CTX *mem_ctx, TRP_MSG_INFO_REC **rec, json_t *jrecord)
+void trp_inforec_free(TRP_INFOREC *rec)
 {
-  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
-  TRP_MSG_INFO_TYPE rectype;
-  TRP_RC rc=TRP_ERROR;
-  char *s=NULL;
-  int num=0;
-  
-  rc=trp_get_json_string(jrecord, "record_type", &s, tmp_ctx);
-  if (rc != TRP_SUCCESS)
-    goto cleanup;
-  rectype=trp_msg_info_type_from_string(s);
-  talloc_free(s); s=NULL;
-
-  (*rec)=trp_msg_info_rec_new(tmp_ctx, rectype);
-  if ((*rec)==NULL) {
-    rc=TRP_NOMEM;
-    goto cleanup;
-  }
-
-  /* We only support route_info records for now*/
-  if ((*rec)->type!=TRP_MSG_INFO_TYPE_ROUTE) {
-    rc=TRP_UNSUPPORTED;
-    goto cleanup;
-  }
-
-  tr_debug("trp_parse_update_record: '%s' record found.", trp_msg_info_type_to_string((*rec)->type));
-
-  rc=trp_get_json_string(jrecord, "community", &s, tmp_ctx);
-  if (rc != TRP_SUCCESS)
-    goto cleanup;
-  if (TRP_SUCCESS!=trp_msg_info_route_set_comm(*rec, tr_new_name(s))) /* assumes route_info */
-    goto cleanup;
-  talloc_free(s); s=NULL;
-
-  rc=trp_get_json_string(jrecord, "realm", &s, tmp_ctx);
-  if (rc != TRP_SUCCESS)
-    goto cleanup;
-  if (TRP_SUCCESS!=trp_msg_info_route_set_realm(*rec, tr_new_name(s))) /* assumes route_info */
-    goto cleanup;
-  talloc_free(s); s=NULL;
-
-  rc=trp_get_json_string(jrecord, "trust_router", &s, tmp_ctx);
-  if (rc != TRP_SUCCESS)
-    goto cleanup;
-  if (TRP_SUCCESS!=trp_msg_info_route_set_trust_router(*rec, tr_new_name(s))) /* assumes route_info */
-    goto cleanup;
-  talloc_free(s); s=NULL;
-
-  rc=trp_get_json_integer(jrecord, "metric", &num);
-  if ((rc != TRP_SUCCESS) || (TRP_SUCCESS!=trp_msg_info_route_set_metric(*rec,num)))
-    goto cleanup;
-
-  rc=trp_get_json_integer(jrecord, "interval", &num);
-  if ((rc != TRP_SUCCESS) || (TRP_SUCCESS!=trp_msg_info_route_set_interval(*rec,num)))
-    goto cleanup;
-
-  talloc_steal(mem_ctx, *rec);
-  rc=TRP_SUCCESS;
-
-cleanup:
-  if (rc != TRP_SUCCESS) {
-    /* kind of a hack, assumes we only have route_info records */
-    trp_msg_info_route_destructor((*rec)->data);
-    (*rec)=NULL;
-  }
-  talloc_free(tmp_ctx);
-  return rc;
+  if (rec!=NULL)
+    talloc_free(rec);
 }
 
-static void *trp_route_update_new(TALLOC_CTX *mem_ctx)
+TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx)
 {
-  TRP_ROUTE_UPDATE *new_body=talloc(mem_ctx, TRP_ROUTE_UPDATE);
+  TRP_UPD *new_body=talloc(mem_ctx, TRP_UPD);
 
   if (new_body!=NULL) {
     new_body->records=NULL;
   }
+  return new_body;
 }
 
-/* Parse an update body. Creates a linked list of records in the msg->body talloc context.
- *
- * An error will be returned if any unparseable records are encountered. 
- *
- * TODO: clean up return codes. 
- * TODO: should take a body, not a msg */
-static TRP_RC trp_parse_route_update(TRP_MSG *msg, json_t *jbody)
+void trp_upd_free(TRP_UPD *update)
 {
-  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
-  json_t *jrecords=NULL;
-  size_t ii=0;
-  size_t nrec=0;
-  TRP_ROUTE_UPDATE *msg_body=NULL;
-  TRP_MSG_INFO_REC *new_rec=NULL;
-  TRP_MSG_INFO_REC *list_tail=NULL;
-  TRP_RC rc=TRP_ERROR;
-
-  if (msg->type != TRP_MSG_TYPE_UPDATE) {
-    rc=TRP_BADTYPE;
-    goto cleanup;
-  }
-  msg_body=talloc_get_type(msg->body, TRP_ROUTE_UPDATE);
-  if (msg_body==NULL) {
-    rc=TRP_BADTYPE;
-    goto cleanup;
-  }
-
-  jrecords=json_object_get(jbody, "records");
-  if ((jrecords==NULL) || (!json_is_array(jrecords))) {
-    rc=TRP_NOPARSE;
-    goto cleanup;
-  }
-
-  tr_debug("trp_parse_route_update: found %d records", json_array_size(jrecords));
-  /* process the array */
-  for (ii=0; ii<json_array_size(jrecords); ii++) {
-    if (TRP_SUCCESS != trp_parse_update_record(tmp_ctx, &new_rec, json_array_get(jrecords, ii))) {
-      rc=TRP_NOPARSE;
-      goto cleanup;
-    }
-
-    if (list_tail==NULL)
-      msg_body->records=new_rec; /* first is a special case */
-    else
-      list_tail->next=new_rec;
-
-    list_tail=new_rec;
-  }
-
-  /* Succeeded. Move all of our new allocations into the correct talloc context */
-  for (list_tail=msg_body->records; list_tail != NULL; list_tail=list_tail->next)
-    talloc_steal(msg->body, list_tail); /* all successfully parsed bodies belong to msg context */
-
-  rc=TRP_SUCCESS;
-
-cleanup:
-  talloc_free(tmp_ctx);
-  if ((rc != TRP_SUCCESS) && (msg_body != NULL))
-    msg_body->records=NULL; /* don't leave this hanging */
-
-  return rc;
+  if (update!=NULL)
+    talloc_free(update);
 }
 
+
 /* pretty print */
-static void trp_msg_info_route_print(void *rec_in)
+static void trp_inforec_route_print(TRP_INFOREC_DATA data)
 {
-  TRP_MSG_INFO_ROUTE *rec=talloc_get_type(rec_in, TRP_MSG_INFO_ROUTE); /* null if wrong type */
-
-  if (rec!=NULL) {
+  if (data.route!=NULL) {
     printf("     community=%.*s\n     realm=%.*s\n     trust_router=%.*s\n     metric=%d\n     interval=%d]\n",
-           rec->comm->len, rec->comm->buf,
-           rec->realm->len, rec->realm->buf,
-           rec->trust_router->len, rec->trust_router->buf,
-           rec->metric, rec->interval);
+           data.route->comm->len, data.route->comm->buf,
+           data.route->realm->len, data.route->realm->buf,
+           data.route->trust_router->len, data.route->trust_router->buf,
+           data.route->metric, data.route->interval);
   }
 }
 
 
-static int trp_route_req_destructor(void *object)
+static int trp_req_destructor(void *object)
 {
-  TRP_ROUTE_REQ *body=talloc_get_type_abort(object, TRP_ROUTE_REQ);
+  TRP_REQ *body=talloc_get_type_abort(object, TRP_REQ);
   
   /* clean up TR_NAME data, which are not managed by talloc */
   if (body->comm != NULL) {
     tr_free_name(body->comm);
     body->comm=NULL;
-    tr_debug("trp_route_req_destructor: freed community");
+    tr_debug("trp_req_destructor: freed community");
   }
   if (body->realm != NULL) {
     tr_free_name(body->realm);
     body->realm=NULL;
-    tr_debug("trp_route_req_destructor: freed realm");
+    tr_debug("trp_req_destructor: freed realm");
   }
   return 0;
 }
 
-void *trp_route_req_new(TALLOC_CTX *mem_ctx)
+TRP_REQ *trp_req_new(TALLOC_CTX *mem_ctx)
 {
-  TRP_ROUTE_REQ *new_body=talloc(mem_ctx, TRP_ROUTE_REQ);
+  TRP_REQ *new_body=talloc(mem_ctx, TRP_REQ);
 
   if (new_body != NULL) {
     new_body->comm=NULL;
     new_body->realm=NULL;
   }
 
-  talloc_set_destructor((void *)new_body, trp_route_req_destructor);
+  talloc_set_destructor((void *)new_body, trp_req_destructor);
   return new_body;
 }
 
-void trp_route_req_set_comm(TRP_ROUTE_REQ *req, TR_NAME *comm)
+void trp_req_free(TRP_REQ *req)
 {
-  req->comm=comm;
+  if (req!=NULL)
+    talloc_free(req);
 }
 
-void trp_route_req_set_realm(TRP_ROUTE_REQ *req, TR_NAME *realm)
-{
-  req->realm=realm;
-}
-
-/* TODO: clean up return codes. 
- * TODO: should take a body, not a msg */
-static TRP_RC trp_parse_route_req(TRP_MSG *msg, json_t *jbody)
-{
-  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
-  TRP_ROUTE_REQ *msg_body=NULL;
-  char *s=NULL;
-  TRP_RC rc=TRP_ERROR;
-
-  /* check message type and body type for agreement */
-  if (msg->type != TRP_MSG_TYPE_ROUTE_REQ) {
-    rc=TRP_BADTYPE;
-    goto cleanup;
-  }
-  msg_body=talloc_get_type(msg->body, TRP_ROUTE_REQ);
-  if (msg_body==NULL) {
-    rc=TRP_BADTYPE;
-    goto cleanup;
-  }
-
-  rc=trp_get_json_string(jbody, "community", &s, tmp_ctx);
-  if (rc!=TRP_SUCCESS)
-    goto cleanup;
-  msg_body->comm=tr_new_name(s);
-  talloc_free(s); s=NULL;
-
-  rc=trp_get_json_string(jbody, "realm", &s, tmp_ctx);
-  if (rc!=TRP_SUCCESS)
-    goto cleanup;
-  msg_body->realm=tr_new_name(s);
-  talloc_free(s); s=NULL;
-
-  rc=TRP_SUCCESS;
-cleanup:
-  talloc_free(tmp_ctx);
-  return rc;
-}
-
-static json_t *trp_encode_body(TRP_MSG_TYPE type, void *body)
-{
-  struct trp_msg_type_entry *msgtype=get_trp_msg_type_entry(type);
-
-  if ((msgtype->type==TRP_MSG_TYPE_UNKNOWN) || (msgtype->encode==NULL))
-    return NULL;
-
-  return msgtype->encode(body);
-}
-
-char *trp_encode_msg(TRP_MSG *msg)
-{
-  json_t *jmsg=NULL;
-  json_t *jtype=NULL;
-  json_t *jbody=NULL;
-  char *encoded=NULL;
-
-  jbody=trp_encode_body(msg->type, msg->body);
-  if (jbody!=NULL) {
-    jmsg=json_object();
-    if (jmsg==NULL) {
-      /* failed */
-      json_decref(jbody);
-    } else {
-      jtype=json_string(trp_msg_type_to_string(msg->type));
-      if (jtype==NULL) {
-        json_decref(jbody);
-      } else {
-        json_object_set_new(jmsg, "message_type", jtype);
-        json_object_set_new(jmsg, "body", jbody);
-        encoded=json_dumps(jmsg, 0);
-      }
-      json_decref(jmsg);
-    }
-  }
-  return encoded;
-}
-
-/* add record data to jrec */
-static TRP_RC trp_encode_info_route(json_t *jrec, void *route_in)
-{
-  TRP_MSG_INFO_ROUTE *route=talloc_get_type(route_in, TRP_MSG_INFO_ROUTE);
-  json_t *jstr=NULL;
-  json_t *jint=NULL;
-  char *s=NULL;
-
-  if (route==NULL)
-    return TRP_BADTYPE;
-
-  s=tr_name_strdup(route->comm);
-  if (s==NULL)
-    return TRP_NOMEM;
-  jstr=json_string(s);
-  free(s);s=NULL;
-  if(jstr==NULL)
-    return TRP_ERROR;
-  json_object_set_new(jrec, "community", jstr);
-
-  s=tr_name_strdup(route->realm);
-  if (s==NULL)
-    return TRP_NOMEM;
-  jstr=json_string(s);
-  free(s);s=NULL;
-  if(jstr==NULL)
-    return TRP_ERROR;
-  json_object_set_new(jrec, "realm", jstr);
-
-  s=tr_name_strdup(route->trust_router);
-  if (s==NULL)
-    return TRP_NOMEM;
-  jstr=json_string(s);
-  free(s);s=NULL;
-  if(jstr==NULL)
-    return TRP_ERROR;
-  json_object_set_new(jrec, "trust_router", jstr);
-
-  jint=json_integer(route->metric);
-  if(jint==NULL)
-    return TRP_ERROR;
-  json_object_set_new(jrec, "metric", jint);
-
-  jint=json_integer(route->interval);
-  if(jint==NULL)
-    return TRP_ERROR;
-  json_object_set_new(jrec, "interval", jint);
-
-  return TRP_SUCCESS;
-}
-
-static json_t *trp_encode_info_rec(TRP_MSG_INFO_REC *rec)
-{
-  struct trp_msg_info_type_entry *rectype=get_trp_msg_info_type_entry(rec->type);
-  json_t *jrec=NULL;
-  json_t *jstr=NULL;
-
-  if (rectype->type==TRP_MSG_INFO_TYPE_UNKNOWN)
-    return NULL;
-
-  jrec=json_object();
-  if (jrec==NULL)
-    return NULL;
-
-  jstr=json_string(trp_msg_info_type_to_string(rec->type));
-  if (jstr==NULL) {
-    json_decref(jrec);
-    return NULL;
-  }
-  json_object_set_new(jrec, "record_type", jstr);
-
-  if ((rectype->encode==NULL) || (TRP_SUCCESS!=rectype->encode(jrec, rec->data))) {
-    json_decref(jrec);
-    return NULL;
-  }
-
-  return jrec;
-}
-
-static json_t *trp_encode_route_update(void *update_in)
-{
-  TRP_ROUTE_UPDATE *update=talloc_get_type(update_in, TRP_ROUTE_UPDATE); /* null if wrong type */
-  json_t *jbody=NULL;
-  json_t *jrecords=NULL;
-  json_t *jrec=NULL;
-  TRP_MSG_INFO_REC *rec;
-
-  if (update==NULL)
-    return NULL;
-
-  jbody=json_object();
-  if (jbody==NULL)
-    return NULL;
-
-  jrecords=json_array();
-  if (jrecords==NULL) {
-    json_decref(jbody);
-    return NULL;
-  }
-  json_object_set_new(jbody, "records", jrecords); /* jrecords now a "borrowed" reference */
-  for (rec=update->records; rec!=NULL; rec=rec->next) {
-    jrec=trp_encode_info_rec(rec);
-    if (jrec==NULL) {
-      json_decref(jbody); /* also decs jrecords and any elements */
-      return NULL;
-    }
-    if (0!=json_array_append_new(jrecords, jrec)) {
-      json_decref(jbody); /* also decs jrecords and any elements */
-      json_decref(jrec); /* this one did not get added so dec explicitly */
-      return NULL;
-    }
-  }
-
-  return jbody;
-}
-
-static json_t *trp_encode_route_req(void *req_in)
-{
-  TRP_ROUTE_REQ *req=talloc_get_type(req_in, TRP_ROUTE_REQ); /* null if wrong type */
-  json_t *jbody=NULL;
-  json_t *jstr=NULL;
-  char *s=NULL;
-
-  if (req==NULL)
-    return NULL;
-
-  jbody=json_object();
-  if (jbody==NULL)
-    return NULL;
-
-  s=tr_name_strdup(req->comm); /* ensures null termination */
-  if (s==NULL) {
-    json_decref(jbody);
-    return NULL;
-  }
-  jstr=json_string(s);
-  free(s); s=NULL;
-  if (jstr==NULL) {
-    json_decref(jbody);
-    return NULL;
-  }
-  json_object_set_new(jbody, "community", jstr);
-    
-  s=tr_name_strdup(req->realm); /* ensures null termination */
-  if (s==NULL) {
-    json_decref(jbody);
-    return NULL;
-  }
-  jstr=json_string(s);
-  free(s); s=NULL;
-  if (jstr==NULL) {
-    json_decref(jbody);
-    return NULL;
-  }
-  json_object_set_new(jbody, "realm", jstr);
-
-  return jbody;
-}
-
-static void trp_msg_info_rec_print(TRP_MSG_INFO_REC *rec)
-{
-  struct trp_msg_info_type_entry *rectype=get_trp_msg_info_type_entry(rec->type);
-
-  if (rectype->print != NULL) {
-    printf("    [record_type=%s\n", trp_msg_info_type_to_string(rec->type));
-    rectype->print(rec->data);
-  }
-  else
-    printf("    [record_type=%s, (no print method)]\n");
-}
-
-static void trp_route_update_print(void *body_in)
-{
-  TRP_ROUTE_UPDATE *body=talloc_get_type(body_in, TRP_ROUTE_UPDATE); /* null if wrong type */
-  TRP_MSG_INFO_REC *rec=NULL;
-
-  if (body!=NULL) {
-    printf("  {records=\n");
-    for (rec=body->records; rec!=NULL; rec=rec->next) 
-      trp_msg_info_rec_print(rec);
-    printf("  }\n");
-  }
-}
-
-static void trp_route_req_print(void *body_in)
-{
-  TRP_ROUTE_REQ *body=talloc_get_type(body_in, TRP_ROUTE_REQ); /* null if wrong type */
-
-  if (body!=NULL) {
-    printf("  {community=%.*s\n   realm=%.*s}\n",
-           body->comm->len, body->comm->buf,
-           body->realm->len, body->realm->buf);
-  }
-}
-
-static void trp_msg_body_print(void *body, TRP_MSG_TYPE msgtype)
-{
-  struct trp_msg_type_entry *info=get_trp_msg_type_entry(msgtype);
-  info->print(body);
-}
-
-void trp_msg_print(TRP_MSG *msg)
-{
-  /* right now just assumes update */
-  printf("{message_type=%s\n", trp_msg_type_to_string(msg->type));
-  trp_msg_body_print(msg->body, msg->type);
-  printf("}\n");
-}
-
-/* returns a pointer to one of the message body types, or NULL on error/unknown type */
-static void *trp_msg_body_new(TALLOC_CTX *mem_ctx, TRP_MSG_TYPE msgtype)
-{
-  void *new_body=NULL;
-  struct trp_msg_type_entry *info=get_trp_msg_type_entry(msgtype);
-
-  if (info->type==TRP_MSG_TYPE_UNKNOWN) {
-    tr_debug("trp_msg_body_new: Unknown type %d.", info->type);
-    return NULL;
-  }
-
-  new_body=info->allocate(mem_ctx);
-  msg_body_type_check(msgtype, new_body); /* aborts program on type violation */
-  return new_body;
-}
-
-/* call the correct parser */
-static TRP_RC trp_parse_msg_body(TRP_MSG *msg, json_t *jbody)
-{
-  struct trp_msg_type_entry *info=get_trp_msg_type_entry(msg->type);
-
-  if (info->type==TRP_MSG_TYPE_UNKNOWN) {
-    tr_debug("trp_msg_body_parse: Unknown type %d.", info->type);
-    return TRP_ERROR;
-  }
-
-  return info->parse(msg, jbody);
-}
-
-
-TRP_RC trp_parse_msg(TALLOC_CTX *mem_ctx, const char *buf, size_t buflen, TRP_MSG **msg) 
-{
-  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
-  TRP_MSG *new_msg=NULL;
-  TRP_RC msg_rc=TRP_ERROR;
-  json_error_t json_err;
-  json_t *jmsg=NULL; /* handle for the whole msg */
-  json_t *jbody=NULL;
-  char *s;
-
-  tr_debug("trp_parse_msg: parsing %d bytes", buflen);
-
-  jmsg=json_loadb(buf, buflen, 0, &json_err);
-  if (jmsg == NULL) {
-    tr_debug("trp_parse_msg: Error parsing message.");
-    msg_rc=TRP_NOPARSE;
-    goto cleanup;
-  }
-
-  /* parse the common part of the message */
-  new_msg=trp_msg_new(tmp_ctx);
-  if (new_msg == NULL) {
-    tr_debug("trp_parse_msg: Error allocating message.");
-    msg_rc=TRP_NOMEM;
-    goto cleanup;
-  }
-
-  switch (trp_get_json_string(jmsg, "message_type", &s, new_msg)) {
-  case TRP_SUCCESS:
-    break;
-  case TRP_NOPARSE:
-    tr_debug("trp_parse_msg: required attribute 'message_type' not present.");
-    msg_rc=TRP_NOPARSE;
-    goto cleanup;
-  case TRP_BADTYPE:
-    tr_debug("trp_parse_msg: required attribute 'message_type' is not a string.");
-    msg_rc=TRP_NOPARSE;
-    goto cleanup;
-  default:
-    tr_debug("trp_parse_msg: error parsing 'message_type'.");
-    msg_rc=TRP_NOPARSE;
-    goto cleanup;
-  }
-  
-  tr_debug("trp_parse_msg: 'message_type' is '%s'", s);
-  new_msg->type = trp_msg_type_from_string(s);
-  if (new_msg->type==TRP_MSG_TYPE_UNKNOWN) {
-    tr_debug("trp_parse_msg: Parsing error, unknown message_type (%s).", s);
-    msg_rc=TRP_NOPARSE;
-    goto cleanup;
-  }  
-
-  new_msg->body=trp_msg_body_new(new_msg, new_msg->type);
-  if (new_msg->body==NULL) {
-    tr_debug("trp_parse_msg: Error allocating message body for message_type %d.", new_msg->type);
-    msg_rc=TRP_NOMEM;
-    goto cleanup;
-  }
-  jbody=json_object_get(jmsg, "body");
-  if (jbody==NULL) {
-    tr_debug("trp_parse_msg: Message body not found.");
-    msg_rc=TRP_NOPARSE;
-    goto cleanup;
-  }
-
-  switch (trp_parse_msg_body(new_msg, jbody)) {
-  case TRP_SUCCESS:
-    break;
-  default:
-    tr_debug("trp_parse_msg: Error parsing message body.");
-    goto cleanup;
-  }
-
-  /* success! */
-  (*msg)=new_msg;
-  new_msg=NULL;
-  talloc_steal(mem_ctx, *msg);
-  msg_rc=TRP_SUCCESS;
-
-cleanup:
-  talloc_free(tmp_ctx);
-  json_decref(jmsg);
-  return msg_rc;
-}