Add support for show communities monitoring request
[trust_router.git] / common / tr_comm_encoders.c
1 /*
2  * Copyright (c) 2012-2018, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <jansson.h>
36 #include <tr_idp.h>
37 #include <tr_comm.h>
38 #include <tr_util.h>
39 #include <tr_debug.h>
40
41 /* helper */
42 static json_t *expiry_to_json_string(TR_COMM_MEMB *memb)
43 {
44   struct timespec ts_zero = {0, 0};
45   char *s = NULL;
46   json_t *jstr = NULL;
47
48   if (tr_cmp_timespec(tr_comm_memb_get_expiry(memb), &ts_zero) == 0) {
49     s = strdup("");
50   } else {
51     s = timespec_to_str(tr_comm_memb_get_expiry(memb));
52   }
53
54   if (s) {
55     jstr = json_string(s);
56     free(s);
57   }
58
59   return jstr;
60 }
61
62 /**
63  * Get the provenance from the member, handling empty provenance safely
64  */
65 static json_t *provenance_to_json(TR_COMM_MEMB *memb)
66 {
67   json_t *prov = tr_comm_memb_get_provenance(memb);
68
69   if (prov) {
70     json_incref(prov);
71     return prov;
72   } else {
73     return json_array();
74   }
75 }
76
77 /* helper for below */
78 #define OBJECT_SET_OR_FAIL(jobj, key, val)     \
79 do {                                           \
80   if (val)                                     \
81     json_object_set_new((jobj),(key),(val));   \
82   else                                         \
83     goto cleanup;                              \
84 } while (0)
85
86 json_t *tr_comm_memb_to_json(TR_COMM_MEMB *memb)
87 {
88   json_t *memb_json = NULL;
89   json_t *retval = NULL;
90
91   memb_json = json_object();
92   if (memb_json == NULL)
93     goto cleanup;
94
95   OBJECT_SET_OR_FAIL(memb_json, "realm",
96                      tr_name_to_json_string(tr_comm_memb_get_realm_id(memb)));
97   OBJECT_SET_OR_FAIL(memb_json, "expires",
98                      expiry_to_json_string(memb));
99   OBJECT_SET_OR_FAIL(memb_json, "announce_interval",
100                      json_integer(tr_comm_memb_get_interval(memb)));
101   OBJECT_SET_OR_FAIL(memb_json, "times_expired",
102                      json_integer(tr_comm_memb_get_times_expired(memb)));
103   OBJECT_SET_OR_FAIL(memb_json, "provenance",
104                      provenance_to_json(memb));
105
106   /* succeeded - set the return value and increment the reference count */
107   retval = memb_json;
108   json_incref(retval);
109
110 cleanup:
111   if (memb_json)
112     json_decref(memb_json);
113   return retval;
114 }
115
116 json_t *tr_comm_idp_realms_to_json(TR_COMM_TABLE *ctable, TR_NAME *comm_name)
117 {
118   json_t *jarray = json_array();
119   TR_COMM_ITER *iter = NULL;
120   TR_IDP_REALM *idp = NULL;
121   TR_COMM_MEMB *memb = NULL;
122
123   iter = tr_comm_iter_new(NULL);
124   idp = tr_idp_realm_iter_first(iter, ctable, comm_name);
125   while(idp) {
126     tr_debug("<<<<<<<<<<<<<<<<<<<<<<<<< GOT IDP REALM %s", tr_idp_realm_get_id(idp)->buf);
127     memb = tr_comm_table_find_idp_memb(ctable,
128                                        tr_idp_realm_get_id(idp),
129                                        comm_name);
130     tr_debug("<<<<<<<<<<<<<<<<<<<<<<<<< FOUND MEMB %p", memb);
131     json_array_append_new(jarray, tr_comm_memb_to_json(memb));
132     idp = tr_idp_realm_iter_next(iter);
133   }
134   tr_comm_iter_free(iter);
135
136   return jarray;
137 }
138
139 json_t *tr_comm_rp_realms_to_json(TR_COMM_TABLE *ctable, TR_NAME *comm_id)
140 {
141   json_t *jarray = json_array();
142   TR_COMM_ITER *iter = NULL;
143   TR_RP_REALM *rp = NULL;
144   TR_COMM_MEMB *memb = NULL;
145
146   iter = tr_comm_iter_new(NULL);
147   rp = tr_rp_realm_iter_first(iter, ctable, comm_id);
148   while(rp) {
149     tr_debug("<<<<<<<<<<<<<<<<<<<<<<<<< GOT RP REALM ");
150     memb = tr_comm_table_find_rp_memb(ctable,
151                                       tr_rp_realm_get_id(rp),
152                                       comm_id);
153     json_array_append_new(jarray, tr_comm_memb_to_json(memb));
154     rp = tr_rp_realm_iter_next(iter);
155   }
156   tr_comm_iter_free(iter);
157
158   return jarray;
159 }
160
161 /**
162  * Convert TR_NAME n to a JSON string, returning the empty string if n is null
163  */
164 static json_t *safe_name_to_json_string(TR_NAME *n)
165 {
166   if (n)
167     return tr_name_to_json_string(n);
168   else
169     return json_string("");
170 }
171
172 json_t *tr_comm_to_json(TR_COMM_TABLE *ctable, TR_COMM *comm)
173 {
174   json_t *comm_json = NULL;
175   json_t *retval = NULL;
176
177   comm_json = json_object();
178   if (comm_json == NULL)
179     goto cleanup;
180
181   OBJECT_SET_OR_FAIL(comm_json, "type",
182                      json_string(tr_comm_type_to_str(tr_comm_get_type(comm))));
183   if (tr_comm_get_type(comm) == TR_COMM_APC) {
184     OBJECT_SET_OR_FAIL(comm_json, "expiration_interval",
185                        json_integer(comm->expiration_interval));
186   } else {
187     /* just get the first apc */
188     OBJECT_SET_OR_FAIL(comm_json, "apc",
189                        tr_name_to_json_string(
190                            tr_apc_get_id(
191                                tr_comm_get_apcs(comm))));
192   }
193   OBJECT_SET_OR_FAIL(comm_json, "name",
194                      tr_name_to_json_string(tr_comm_get_id(comm)));
195   OBJECT_SET_OR_FAIL(comm_json, "owner_realm",
196                      safe_name_to_json_string(tr_comm_get_owner_realm(comm)));
197   OBJECT_SET_OR_FAIL(comm_json, "owner_contact",
198                      safe_name_to_json_string(tr_comm_get_owner_contact(comm)));
199
200   OBJECT_SET_OR_FAIL(comm_json, "idp_realms",
201                      tr_comm_idp_realms_to_json(ctable, tr_comm_get_id(comm)));
202   OBJECT_SET_OR_FAIL(comm_json, "rp_realms",
203                      tr_comm_rp_realms_to_json(ctable, tr_comm_get_id(comm)));
204
205   /* succeeded - set the return value and increment the reference count */
206   retval = comm_json;
207   json_incref(retval);
208
209   cleanup:
210   if (comm_json)
211     json_decref(comm_json);
212   return retval;
213 }
214
215 json_t *tr_comm_table_to_json(TR_COMM_TABLE *ctable)
216 {
217   json_t *ctable_json = NULL;
218   json_t *retval = NULL;
219   json_t *comm_json = NULL;
220   TR_COMM_ITER *iter = NULL;
221   TR_COMM *comm = NULL;
222
223   ctable_json = json_array();
224   if (ctable_json == NULL)
225     goto cleanup;
226
227   iter = tr_comm_iter_new(NULL);
228   if (iter == NULL)
229     goto cleanup;
230
231   /* Iterate over communities in the table */
232   comm = tr_comm_table_iter_first(iter, ctable);
233   while (comm) {
234     comm_json = tr_comm_to_json(ctable, comm);
235
236     if (comm_json == NULL)
237       goto cleanup;
238
239     json_array_append_new(ctable_json, comm_json);
240     comm = tr_comm_table_iter_next(iter);
241   }
242
243   /* succeeded - set the return value and increment the reference count */
244   retval = ctable_json;
245   json_incref(retval);
246
247 cleanup:
248   if (iter)
249     tr_comm_iter_free(iter);
250
251   if (ctable_json)
252     json_decref(ctable_json);
253
254   return retval;
255  
256 }