From ad35805c37f0ff03b65c4d7e554e289f9c3d7e00 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Mon, 13 Jun 2016 23:52:03 -0400 Subject: [PATCH] Beginning of JSON parser for TRP messages (nonfunctional) --- include/trp_internal.h | 53 +++++++++++-- trp/msgtst.c | 51 ++++++++++++ trp/trp_msg.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+), 7 deletions(-) create mode 100644 trp/msgtst.c create mode 100644 trp/trp_msg.c diff --git a/include/trp_internal.h b/include/trp_internal.h index 2557ddc..0cf6f05 100644 --- a/include/trp_internal.h +++ b/include/trp_internal.h @@ -7,17 +7,56 @@ #include #define TRP_PORT 12310 +#define TRP_METRIC_INFINITY 0xFFFF + +typedef enum trp_rc { + TRP_SUCCESS=0, + TRP_ERROR, /* generic error */ + TRP_NOPARSE, /* parse error */ + TRP_NOMEM, /* allocation error */ +} 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; + +typedef struct trp_msg { + TRP_MSG_TYPE type; + void *body; +} TRP_MSG; + +typedef struct trp_msg_body_update TRP_MSG_BODY_UPDATE; +struct trp_msg_body_update { + TRP_MSG_BODY_UPDATE *next; + TR_NAME *community; + TR_NAME *realm; + TR_NAME *trust_router; + unsigned int metric; + unsigned int interval; +}; + +typedef struct trp_msg_body_route_req { + TR_NAME *community; + TR_NAME *realm; +} TRP_MSG_BODY_ROUTE_REQ; + +TRP_MSG_TYPE trp_msg_type_from_string(const char *s); +const char *trp_msg_type_to_string(TRP_MSG_TYPE msgtype); -typedef struct trp_req { - int msg; -} TRP_REQ; +TRP_MSG *trp_msg_new(TALLOC_CTX *mem_ctx); +void trp_msg_destroy(TRP_MSG *msg); -typedef struct trp_resp { - int msg; -} TRP_RESP; 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_auth_func)(gss_name_t client_name, TR_NAME *display_name, void *cookie); @@ -30,7 +69,7 @@ typedef struct trps_connection { } TRPS_CONNECTION; /* a collection of the above */ -#define TRPS_CONNECTIONS_MAX 10; +#define TRPS_CONNECTIONS_MAX 10 typedef struct trps_connection_set { TRPS_CONNECTION *conn[TRPS_CONNECTIONS_MAX]; unsigned int nconn; diff --git a/trp/msgtst.c b/trp/msgtst.c new file mode 100644 index 0000000..83f5476 --- /dev/null +++ b/trp/msgtst.c @@ -0,0 +1,51 @@ +/* Testing trp message encoding / decoding */ + +/* compiles with: gcc -o msgtst -I../include msgtst.c trp_msg.c $(pkg-config --cflags --libs glib-2.0) ../common/tr_debug.c -ltalloc -ljansson */ + +#include +#include +#include + +#define MAX_MSG_LEN 8192 + +int main(int argc, const char *argv[]) +{ + FILE *f; + char *buf; + size_t buflen; + TRP_RC rc; + TRP_MSG *msg; + + if (argc != 2) { + printf("Usage: %s \n\n", argv[0]); + exit(-1); + } + + buf=malloc(MAX_MSG_LEN); + if (!buf) { + printf("Allocation error.\n\n"); + exit(-1); + } + + f=fopen(argv[1], "r"); + if (!f) { + printf("Error opening %s for reading.\n\n", argv[1]); + exit(-1); + } + + printf("Reading from %s...\n", argv[1]); + + buflen=fread(buf, sizeof(char), MAX_MSG_LEN, f); + if (buflen==0) { + printf("File empty.\n\n"); + exit(0); + } + + if (buflen>=MAX_MSG_LEN) + printf("Warning: file may exceed maximum message length (%d bytes).\n", MAX_MSG_LEN); + + rc=trp_parse_msg(NULL, buf, buflen, &msg); + printf("trp_parse_msg returned %d\n\n", rc); + + return 0; +} diff --git a/trp/trp_msg.c b/trp/trp_msg.c new file mode 100644 index 0000000..df8fca5 --- /dev/null +++ b/trp/trp_msg.c @@ -0,0 +1,208 @@ +#include + +#include +#include + + +/* static prototypes */ +static void *trp_msg_body_update_new(TALLOC_CTX *mem_ctx); +static void *trp_msg_body_route_req_new(TALLOC_CTX *mem_ctx); + +/* table of string names for TMT_MSG_TYPE codes */ +struct trp_msg_type_info { + const char *name; + TRP_MSG_TYPE type; + void *(*allocator)(TALLOC_CTX *); +}; + +static struct trp_msg_type_info trp_msg_type_table[] = { + { "update", TRP_MSG_TYPE_UPDATE, trp_msg_body_update_new }, + { "route_req", TRP_MSG_TYPE_ROUTE_REQ, trp_msg_body_route_req_new }, + { NULL, TRP_MSG_TYPE_UNKNOWN, 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_MSG_BODY_UPDATE); + break; + + case TRP_MSG_TYPE_ROUTE_REQ: + talloc_get_type_abort(p, TRP_MSG_BODY_ROUTE_REQ); + break; + + default: + break; + } +} + +/* look up an entry in the trp_msg_type_table */ +static struct trp_msg_type_info *get_trp_msg_type_info(TRP_MSG_TYPE msgtype) +{ + struct trp_msg_type_info *entry=trp_msg_type_table; + + while ((entry->type != TRP_MSG_TYPE_UNKNOWN) + && (entry->type != msgtype)) { + entry ++; + } + return entry; +} + +/* translate strings to codes */ +TRP_MSG_TYPE trp_msg_type_from_string(const char *s) +{ + struct trp_msg_type_info *entry=trp_msg_type_table; + + while ((entry->type != TRP_MSG_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_type_to_string(TRP_MSG_TYPE msgtype) +{ + struct trp_msg_type_info *entry=get_trp_msg_type_info(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_TYPE_UNKNOWN; + new_msg->body=NULL; + } + return new_msg; +} + +void trp_msg_destroy(TRP_MSG *msg) +{ + if (msg) + talloc_free(msg); +} + +static void *trp_msg_body_update_new(TALLOC_CTX *mem_ctx) +{ + TRP_MSG_BODY_UPDATE *new_body=talloc(mem_ctx, TRP_MSG_BODY_UPDATE); + + if (new_body != NULL) { + new_body->next=NULL; + new_body->community=NULL; + new_body->realm=NULL; + new_body->trust_router=NULL; + new_body->metric=TRP_METRIC_INFINITY; + new_body->interval=0; + } + return new_body; +} + +/* placeholder return type */ +static int trp_parse_msg_update(json_t *jmsg) +{ + +} + +static void *trp_msg_body_route_req_new(TALLOC_CTX *mem_ctx) +{ + TRP_MSG_BODY_ROUTE_REQ *new_body=talloc(mem_ctx, TRP_MSG_BODY_ROUTE_REQ); + + if (new_body != NULL) { + new_body->community=NULL; + new_body->realm=NULL; + } + return new_body; +} + +/* 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_info *info=get_trp_msg_type_info(msgtype); + + if (info->type==TRP_MSG_TYPE_UNKNOWN) { + tr_debug("trp_msg_body_new: Unknown type %d.", info->type); + return NULL; + } + + new_body=info->allocator(mem_ctx); + msg_body_type_check(msgtype, new_body); /* aborts program on type violation */ + return new_body; +} + + +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 *jmsgtype=NULL; + + 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; + } + + jmsgtype=json_object_get(jmsg, "message_type"); + if (jmsgtype == NULL) { + msg_rc=TRP_NOPARSE; + goto cleanup; + } + + /* get the message type */ + if (!json_is_string(jmsgtype)) { + tr_debug("trp_parse_msg: Parsing error, message_type is not a string."); + msg_rc=TRP_NOPARSE; + goto cleanup; + } + + tr_debug("trp_parse_msg: message_type: %s", json_string_value(jmsgtype)); + + new_msg->type = trp_msg_type_from_string(json_string_value(jmsgtype)); + if (new_msg->type==TRP_MSG_TYPE_UNKNOWN) { + tr_debug("trp_parse_msg: Parsing error, unknown message_type (%s).", json_string_value(jmsgtype)); + msg_rc=TRP_NOPARSE; + goto cleanup; + } + + /* next line uses new_msg as the talloc context so body will free along with msg */ + 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; + } + + tr_debug("trp_parse_msg: SUCCESS"); + + /* success! */ + (*msg)=new_msg; + new_msg=NULL; + talloc_steal(mem_ctx, *msg); + +cleanup: + talloc_free(tmp_ctx); + return msg_rc; +} -- 2.1.4