3 #include <trp_internal.h>
7 /* static prototypes */
8 static void *trp_msg_body_update_new(TALLOC_CTX *mem_ctx);
9 static TRP_RC trp_parse_update(TRP_MSG *msg, json_t *jmsg);
11 static void *trp_msg_body_route_req_new(TALLOC_CTX *mem_ctx);
12 static TRP_RC trp_parse_route_req(TRP_MSG *msg, json_t *jmsg);
15 /* table of string names for TMT_MSG_TYPE codes */
16 struct trp_msg_type_info {
19 void *(*allocator)(TALLOC_CTX *);
20 TRP_RC (*parser)(TRP_MSG *, json_t *);
23 static struct trp_msg_type_info trp_msg_type_table[] = {
24 { "update", TRP_MSG_TYPE_UPDATE, trp_msg_body_update_new, trp_parse_update },
25 { "route_req", TRP_MSG_TYPE_ROUTE_REQ, trp_msg_body_route_req_new, trp_parse_route_req },
26 { NULL, TRP_MSG_TYPE_UNKNOWN, NULL, NULL } /* must be the last entry */
29 /* Use talloc's dynamic type checking to verify type.
30 * By default, this will cause program abort, but can be overridden
31 * via talloc_set_abort_fn() if more graceful handling is needed. */
32 static void msg_body_type_check(TRP_MSG_TYPE msgtype, void *p)
35 case TRP_MSG_TYPE_UPDATE:
36 talloc_get_type_abort(p, TRP_MSG_BODY_UPDATE);
39 case TRP_MSG_TYPE_ROUTE_REQ:
40 talloc_get_type_abort(p, TRP_MSG_BODY_ROUTE_REQ);
48 /* look up an entry in the trp_msg_type_table */
49 static struct trp_msg_type_info *get_trp_msg_type_info(TRP_MSG_TYPE msgtype)
51 struct trp_msg_type_info *entry=trp_msg_type_table;
53 while ((entry->type != TRP_MSG_TYPE_UNKNOWN)
54 && (entry->type != msgtype)) {
60 /* translate strings to codes */
61 TRP_MSG_TYPE trp_msg_type_from_string(const char *s)
63 struct trp_msg_type_info *entry=trp_msg_type_table;
65 while ((entry->type != TRP_MSG_TYPE_UNKNOWN)
66 && (strcmp(s, entry->name)!=0)) {
72 /* translate codes to strings (do not need to be freed)
73 * Returns NULL on an unknown code */
74 const char *trp_msg_type_to_string(TRP_MSG_TYPE msgtype)
76 struct trp_msg_type_info *entry=get_trp_msg_type_info(msgtype);
81 TRP_MSG *trp_msg_new(TALLOC_CTX *mem_ctx)
83 TRP_MSG *new_msg=talloc(mem_ctx, TRP_MSG);
85 if (new_msg != NULL) {
86 new_msg->type=TRP_MSG_TYPE_UNKNOWN;
92 void trp_msg_destroy(TRP_MSG *msg)
100 /* Read attribute attr from msg as an integer */
101 static TRP_RC trp_get_json_integer(json_t *msg, const char *attr, int *dest)
106 /* Read attribute attr from msg as a string */
107 static TRP_RC trp_get_json_string(json_t *jmsg, const char *attr, const char **dest)
112 obj=json_object_get(jmsg, attr);
117 if (!json_is_string(obj)) {
121 (*dest)=json_string_value(obj);
127 static void *trp_msg_body_update_new(TALLOC_CTX *mem_ctx)
129 TRP_MSG_BODY_UPDATE *new_body=talloc(mem_ctx, TRP_MSG_BODY_UPDATE);
131 if (new_body != NULL) {
133 new_body->community=NULL;
134 new_body->realm=NULL;
135 new_body->trust_router=NULL;
136 new_body->metric=TRP_METRIC_INFINITY;
137 new_body->interval=0;
142 /* parse a single record */
143 static TRP_RC trp_parse_update_record(TRP_MSG_BODY_UPDATE *body, json_t *jrecord)
148 /* Parse an update body. Creates a linked list of records as the body, allocating all but the first.
149 * Hence, msg->body must be allocated as a TRP_MSG_BODY_UPDATE. All body records will be in the
150 * talloc context of msg.
152 * An error will be returned if any unparseable records are encountered.
154 * TODO: clean up return codes. */
155 static TRP_RC trp_parse_update(TRP_MSG *msg, json_t *jbody)
157 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
158 json_t *jrecords=NULL;
159 json_t *jval=NULL; /* for iteration */
162 TRP_MSG_BODY_UPDATE *msg_body=NULL;
163 TRP_MSG_BODY_UPDATE *cur_body=NULL;
166 if (msg->type != TRP_MSG_TYPE_UPDATE) {
171 jrecords=json_object_get(jbody, "records");
172 if ((jrecords==NULL) || (!json_is_array(jrecords))) {
177 /* process the array */
178 /* first body is already allocated by caller. Check that it is expected type */
179 msg_body=talloc_get_type(msg->body, TRP_MSG_BODY_UPDATE);
180 if (msg_body==NULL) {
186 nrec=json_array_size(jrecords);
187 for (ii=0; ii<nrec; ii++) {
188 jval=json_array_get(jrecords, ii);
190 /* on all but the first, need to allocate space */
191 cur_body->next=trp_msg_body_update_new(tmp_ctx);
192 if (cur_body==NULL) {
196 cur_body=cur_body->next;
199 if (TRP_SUCCESS != trp_parse_update_record(cur_body, jval)) {
205 /* Succeeded. Move all of our new allocations into the correct talloc context */
206 for (cur_body=msg_body->next; cur_body != NULL; cur_body=cur_body->next)
207 talloc_steal(msg, cur_body); /* all successfully parsed bodies belong to msg context */
211 talloc_free(tmp_ctx);
212 if (rc != TRP_SUCCESS)
213 msg_body->next=NULL; /* don't leave this hanging */
219 static void *trp_msg_body_route_req_new(TALLOC_CTX *mem_ctx)
221 TRP_MSG_BODY_ROUTE_REQ *new_body=talloc(mem_ctx, TRP_MSG_BODY_ROUTE_REQ);
223 if (new_body != NULL) {
224 new_body->community=NULL;
225 new_body->realm=NULL;
230 static TRP_RC trp_parse_route_req(TRP_MSG *msg, json_t *jbody)
237 /* returns a pointer to one of the message body types, or NULL on error/unknown type */
238 static void *trp_msg_body_new(TALLOC_CTX *mem_ctx, TRP_MSG_TYPE msgtype)
241 struct trp_msg_type_info *info=get_trp_msg_type_info(msgtype);
243 if (info->type==TRP_MSG_TYPE_UNKNOWN) {
244 tr_debug("trp_msg_body_new: Unknown type %d.", info->type);
248 new_body=info->allocator(mem_ctx);
249 msg_body_type_check(msgtype, new_body); /* aborts program on type violation */
253 /* call the correct parser */
254 static TRP_RC trp_parse_msg_body(TRP_MSG *msg, json_t *jbody)
256 struct trp_msg_type_info *info=get_trp_msg_type_info(msg->type);
258 if (info->type==TRP_MSG_TYPE_UNKNOWN) {
259 tr_debug("trp_msg_body_parse: Unknown type %d.", info->type);
263 return info->parser(msg, jbody);
267 TRP_RC trp_parse_msg(TALLOC_CTX *mem_ctx, const char *buf, size_t buflen, TRP_MSG **msg)
269 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
270 TRP_MSG *new_msg=NULL;
271 TRP_RC msg_rc=TRP_ERROR;
272 json_error_t json_err;
273 json_t *jmsg=NULL; /* handle for the whole msg */
277 tr_debug("trp_parse_msg: parsing %d bytes", buflen);
279 jmsg=json_loadb(buf, buflen, 0, &json_err);
281 tr_debug("trp_parse_msg: Error parsing message.");
286 /* parse the common part of the message */
287 new_msg=trp_msg_new(tmp_ctx);
288 if (new_msg == NULL) {
289 tr_debug("trp_parse_msg: Error allocating message.");
294 switch (trp_get_json_string(jmsg, "message_type", &s)) {
298 tr_debug("trp_parse_msg: required attribute 'message_type' not present.");
302 tr_debug("trp_parse_msg: required attribute 'message_type' is not a string.");
306 tr_debug("trp_parse_msg: error parsing 'message_type'.");
311 tr_debug("trp_parse_msg: 'message_type' is '%s'", s);
312 new_msg->type = trp_msg_type_from_string(s);
313 if (new_msg->type==TRP_MSG_TYPE_UNKNOWN) {
314 tr_debug("trp_parse_msg: Parsing error, unknown message_type (%s).", s);
319 new_msg->body=trp_msg_body_new(new_msg, new_msg->type);
320 if (new_msg->body==NULL) {
321 tr_debug("trp_parse_msg: Error allocating message body for message_type %d.", new_msg->type);
325 jbody=json_object_get(jmsg, "body");
327 tr_debug("trp_parse_msg: Message body not found.");
332 switch (trp_parse_msg_body(new_msg, jbody)) {
336 tr_debug("trp_parse_msg: Error parsing message body.");
343 talloc_steal(mem_ctx, *msg);
346 talloc_free(tmp_ctx);