X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=common%2Ftr_comm.c;h=725fcac27894bbe81a597df59e9ed2eb3727d6ed;hb=e2b95e95ffdc2e72afa22509cf3473e61090d03f;hp=750651f34713c7eab89d5ae2fd492066b6a35d06;hpb=51971d70dac37608fcf04fbaf6b75a50c89d9cbc;p=trust_router.git diff --git a/common/tr_comm.c b/common/tr_comm.c index 750651f..725fcac 100644 --- a/common/tr_comm.c +++ b/common/tr_comm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, JANET(UK) + * Copyright (c) 2012-2018, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,10 +39,11 @@ #include #include -#include +#include +#include #include #include - +#include static int tr_comm_destructor(void *obj) { @@ -246,6 +247,7 @@ void tr_comm_add_idp_realm(TR_COMM_TABLE *ctab, tr_comm_memb_set_comm(newmemb, comm); tr_comm_memb_set_interval(newmemb, interval); tr_comm_memb_set_provenance(newmemb, provenance); + tr_comm_memb_set_expiry(newmemb, expiry); existing=tr_comm_table_find_idp_memb_origin(ctab, tr_idp_realm_get_id(realm), @@ -278,6 +280,7 @@ void tr_comm_add_rp_realm(TR_COMM_TABLE *ctab, tr_comm_memb_set_comm(newmemb, comm); tr_comm_memb_set_interval(newmemb, interval); tr_comm_memb_set_provenance(newmemb, provenance); + tr_comm_memb_set_expiry(newmemb, expiry); existing=tr_comm_table_find_rp_memb_origin(ctab, tr_rp_realm_get_id(realm), @@ -370,10 +373,10 @@ static TR_COMM *tr_comm_sweep_func(TR_COMM *head) return NULL; /* will not remove the head here, that has already been done */ - for (comm=head; comm->next!=NULL; comm=comm->next) { + for (comm=head; (comm!=NULL) && (comm->next!=NULL); comm=comm->next) { if (comm->next->refcount==0) { old_next=comm->next; - tr_comm_remove(head, comm->next); /* changes comm->next */ + tr_comm_remove(head, comm->next); /* changes comm->next, may make it null */ tr_comm_free(old_next); } } @@ -759,9 +762,53 @@ TR_COMM_MEMB *tr_comm_memb_iter_next(TR_COMM_ITER *iter) } -/* iterate over all memberships in the table */ +/* iterate over all memberships in the table + * + * The table is structured as a vertical list of memberships, each for a + * different community/realm. Each element in this list has a horizontal "origin list," + * each for the same community/realm but with a different origin for the membership. + * Only the first element in the origin list has a vertical link ("next" pointer). + * Any element may have a horizontal link ("origin_next" pointer). + * + * (A) - (B) - (C) - X + * | + * (D) - (E) - X + * | + * (F) - X + * | + * (G) - (H) - X + * | + * X + * + * A, B, and C are all community/realm pair membership 1, with different origins + * D, E are a second community/realm pair, with different origins + * F is a third... + * G, H are a fourth pair, with different origins + * + * This iterator will return every element in the grid. + * + * Algorithm: + * The iterator struct stores the current member (cur_memb) and the origin head (cur_orig_head). + * The latter is a pointer to the head of the current origin list (i.e., first element in a row). + * The former can point to any element in the list. Both start at the root of the list (A in the + * diagram above). + * + * After each call to _first() or _next(), cur_memb points to the element just returned. + * + * 0. _first() just returns the first element. The rest of the steps are in _next() + * + * 1. If cur_memb has an origin_next element, walk the origin list. Move cur_memb to + * the origin_list element (next one in this row) and return it. + * 2. If cur_memb does not have an origin_next element, we've finished the current origin + * list. Move cur_memb to cur_orig_head's next element (the start of the next column), + * move cur_orig_head to that same place, and return it. + * 3. If neither cur_memb has an origin_next element nor cur_orig_head has a next element, + * then we have already reached the end of the list and there's nothing more to do. + * Return NULL. + */ TR_COMM_MEMB *tr_comm_memb_iter_all_first(TR_COMM_ITER *iter, TR_COMM_TABLE *ctab) { + /* step 0: return the root of the list */ iter->cur_memb=ctab->memberships; iter->cur_orig_head=ctab->memberships; return iter->cur_memb; @@ -769,16 +816,15 @@ TR_COMM_MEMB *tr_comm_memb_iter_all_first(TR_COMM_ITER *iter, TR_COMM_TABLE *cta TR_COMM_MEMB *tr_comm_memb_iter_all_next(TR_COMM_ITER *iter) { - if (iter->cur_memb->next==NULL) { - if (iter->cur_orig_head->next==NULL) { - /* we're done */ - return NULL; - } else { - iter->cur_memb=iter->cur_orig_head->next; - iter->cur_orig_head=iter->cur_orig_head->next; - } + if (iter->cur_memb->origin_next) { + /* step 1: return the next element in the current origin list */ + iter->cur_memb = iter->cur_memb->origin_next; + } else if (iter->cur_orig_head->next) { + /* step 2: move to the start of the next row and return the first element */ + iter->cur_orig_head = iter->cur_memb = iter->cur_orig_head->next; } else { - iter->cur_memb=iter->cur_memb->origin_next; + /* step 3: both cur_memb->origin_next and cur_orig_head->next are null */ + iter->cur_orig_head = iter->cur_memb = NULL; } return iter->cur_memb; } @@ -1015,8 +1061,25 @@ struct timespec *tr_comm_memb_get_expiry(TR_COMM_MEMB *memb) return memb->expiry; } +/** + * Get the expiration according to the realtime clock + * + * @param memb + * @param result space to store the result + * @return pointer to the result, or null on error + */ +struct timespec *tr_comm_memb_get_expiry_realtime(TR_COMM_MEMB *memb, struct timespec *result) +{ + return tr_clock_convert(TRP_CLOCK, memb->expiry, CLOCK_REALTIME, result); +} + int tr_comm_memb_is_expired(TR_COMM_MEMB *memb, struct timespec *curtime) { + tr_debug("tr_comm_memb_is_expired: (cur->tv_sec>memb->expiry->tv_sec)=(%u > %u)=%s", + curtime->tv_sec, + memb->expiry->tv_sec, + (curtime->tv_sec > memb->expiry->tv_sec)?"true":"false"); + return ((curtime->tv_sec > memb->expiry->tv_sec) || ((curtime->tv_sec == memb->expiry->tv_sec) &&(curtime->tv_nsec >= memb->expiry->tv_nsec))); @@ -1315,11 +1378,24 @@ TR_COMM *tr_comm_table_find_comm(TR_COMM_TABLE *ctab, TR_NAME *comm_id) return tr_comm_lookup(ctab->comms, comm_id); } -void tr_comm_table_add_comm(TR_COMM_TABLE *ctab, TR_COMM *new) +/** + * Add a community to the table. + * + * Does not allow duplicate community ids. + * + * @param ctab + * @param new + * @return 0 on success, -1 on failure + */ +int tr_comm_table_add_comm(TR_COMM_TABLE *ctab, TR_COMM *new) { + if (tr_comm_table_find_comm(ctab, tr_comm_get_id(new)) != NULL) + return -1; + tr_comm_add(ctab->comms, new); if (ctab->comms!=NULL) talloc_steal(ctab, ctab->comms); /* make sure it's in the right context */ + return 0; } void tr_comm_table_remove_comm(TR_COMM_TABLE *ctab, TR_COMM *comm) @@ -1404,40 +1480,77 @@ TR_REALM_ROLE tr_realm_role_from_str(const char *s) return TR_ROLE_UNKNOWN; } -static void tr_comm_table_print_provenance(FILE *f, json_t *prov) +static char *tr_comm_table_append_provenance(char *ctable_s, json_t *prov) { const char *s=NULL; + char *tmp=NULL; size_t ii=0; for (ii=0; ii> Membership table start <<\n"); + ctable_s=talloc_asprintf(tmp_ctx, ">> Membership table start <<\n"); + if (ctable_s==NULL) + goto cleanup; + for (p1=ctab->memberships; p1!=NULL; p1=p1->next) { - fprintf(f, "* %s %s/%s\n %s (%p) - prov: ", - tr_realm_role_to_str(tr_comm_memb_get_role(p1)), - tr_comm_memb_get_realm_id(p1)->buf, - tr_comm_get_id(tr_comm_memb_get_comm(p1))->buf, - (tr_comm_memb_get_origin(p1)==NULL)?"null origin":(tr_comm_memb_get_origin(p1)->buf), - p1); - tr_comm_table_print_provenance(f, p1->provenance); - fprintf(f, "\n"); + append_on_success_helper( + ctable_s, tmp, + talloc_asprintf_append(ctable_s, "* %s %s/%s\n %s (%p) - prov: ", + tr_realm_role_to_str(tr_comm_memb_get_role(p1)), + tr_comm_memb_get_realm_id(p1)->buf, + tr_comm_get_id(tr_comm_memb_get_comm(p1))->buf, + (tr_comm_memb_get_origin(p1)==NULL)?"null origin":(tr_comm_memb_get_origin(p1)->buf), + p1)); + + append_on_success_helper(ctable_s, tmp, tr_comm_table_append_provenance(ctable_s, p1->provenance)); + + append_on_success_helper(ctable_s, tmp, talloc_strdup_append_buffer(ctable_s, "\n")); + for (p2=p1->origin_next; p2!=NULL; p2=p2->origin_next) { - fprintf(f, " %s (%p) - prov: ", - (tr_comm_memb_get_origin(p2)==NULL)?"null origin":(tr_comm_memb_get_origin(p2)->buf), - p2); - tr_comm_table_print_provenance(f, p2->provenance); - fprintf(f, "\n"); + append_on_success_helper( + ctable_s, tmp, + talloc_asprintf_append(ctable_s, " %s (%p) - prov: ", + (tr_comm_memb_get_origin(p2)==NULL)?"null origin":(tr_comm_memb_get_origin(p2)->buf), + p2)); + append_on_success_helper(ctable_s, tmp, tr_comm_table_append_provenance(ctable_s, p2->provenance)); + append_on_success_helper(ctable_s, tmp, talloc_strdup_append_buffer(ctable_s, "\n")); } - fprintf(f, "\n"); + append_on_success_helper(ctable_s, tmp, talloc_strdup_append_buffer(ctable_s, "\n")); } + +cleanup: + if (ctable_s!=NULL) + talloc_steal(mem_ctx, ctable_s); + + talloc_free(tmp_ctx); + return ctable_s; } + +void tr_comm_table_print(FILE *f, TR_COMM_TABLE *ctab) +{ + char *s=tr_comm_table_to_str(NULL, ctab); + if (s!=NULL) { + tr_debug("%s", s); + talloc_free(s); + } +} \ No newline at end of file