#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;
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;
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;
}
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;
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);
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))) {
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;
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);
+ }
}
#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 ++;
}
}
/* 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++;
}
}
/* 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;
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;
-}