Navigation


Changeset 16:013ce9851131 in freeDiameter for freeDiameter/peers.c


Ignore:
Timestamp:
Oct 2, 2009, 6:57:06 PM (15 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Started including TLS code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/peers.c

    r14 r16  
    3636#include "fD.h"
    3737
     38/* Global list of peers */
    3839struct fd_list   fd_g_peers = FD_LIST_INITIALIZER(fd_g_peers);
    3940pthread_rwlock_t fd_g_peers_rw = PTHREAD_RWLOCK_INITIALIZER;
    4041
    41 /* Terminate peer module (destroy all peers) */
    42 int fd_peer_fini()
    43 {
    44         struct fd_list * li;
    45         TRACE_ENTRY();
    46        
    47         CHECK_FCT_DO(fd_p_expi_fini(), /* continue */);
    48        
    49         TRACE_DEBUG(INFO, "Sending signal to terminate to all peer connections");
    50        
    51         CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ );
    52         /* For each peer in the list, ... */
    53         for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
    54                 struct fd_peer * np = (struct fd_peer *)li;
    55                 CHECK_FCT_DO( fd_psm_terminate(np), /* continue */ );
    56         }
    57         CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
    58        
    59         TODO("Give some time to all PSM, then destroy remaining threads");
    60         /* fd_psm_abord(struct fd_peer * peer ) */
    61        
    62         return 0;
    63 }
    64 
    65 /* Dump the list of peers */
    66 void fd_peer_dump_list(int details)
    67 {
    68         struct fd_list * li;
    69        
    70         fd_log_debug("Dumping list of peers :\n");
    71         CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ );
    72        
    73         for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
    74                 struct fd_peer * np = (struct fd_peer *)li;
    75                 if (np->p_eyec != EYEC_PEER) {
    76                         fd_log_debug("  Invalid entry @%p !\n", li);
    77                         continue;
    78                 }
    79                
    80                 fd_log_debug("   %s\t%s", STATE_STR(np->p_hdr.info.pi_state), np->p_hdr.info.pi_diamid);
    81                 if (details > INFO) {
    82                         fd_log_debug("\t(rlm:%s)", np->p_hdr.info.pi_realm);
    83                         if (np->p_hdr.info.pi_prodname)
    84                                 fd_log_debug("\t['%s' %u]", np->p_hdr.info.pi_prodname, np->p_hdr.info.pi_firmrev);
    85                         fd_log_debug("\t(from %s)", np->p_dbgorig);
    86                 }
    87                 fd_log_debug("\n");
    88         }
    89        
    90         CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
    91 }
    9242
    9343/* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */
    94 static int fd_sp_reinit(struct fd_peer ** ptr)
     44int fd_peer_alloc(struct fd_peer ** ptr)
    9545{
    9646        struct fd_peer *p;
     
    12676}
    12777
    128 #define free_null( _v )         \
    129         if (_v) {               \
    130                 free(_v);       \
    131                 (_v) = NULL;    \
    132         }
    133        
    134 #define free_list( _l )                                                 \
    135         while (!FD_IS_LIST_EMPTY(_l)) {                                 \
    136                 struct fd_list * __li = ((struct fd_list *)(_l))->next; \
    137                 fd_list_unlink(__li);                                   \
    138                 free(__li);                                             \
    139         }
    140 
    141 /* Destroy a structure once all cleanups have been performed */
    142 static int fd_sp_destroy(struct fd_peer ** ptr)
    143 {
    144         struct fd_peer *p;
    145         void * t;
    146        
    147         TRACE_ENTRY("%p", ptr);
    148         CHECK_PARAMS(ptr);
    149         p = *ptr;
    150         *ptr = NULL;
    151         CHECK_PARAMS(p);
    152        
    153         CHECK_PARAMS( FD_IS_LIST_EMPTY(&p->p_hdr.chain) );
    154        
    155         free_null(p->p_hdr.info.pi_diamid);
    156         free_null(p->p_hdr.info.pi_realm);
    157         free_list( &p->p_hdr.info.pi_endpoints );
    158         /* Assume the security data is already freed */
    159         free_null(p->p_hdr.info.pi_prodname);
    160         free_list( &p->p_hdr.info.pi_apps );
    161        
    162         free_null(p->p_dbgorig);
    163         ASSERT(FD_IS_LIST_EMPTY(&p->p_expiry));
    164         ASSERT(FD_IS_LIST_EMPTY(&p->p_actives));
    165        
    166         CHECK_FCT( fd_thr_term(&p->p_psm) );
    167         while ( fd_fifo_tryget(p->p_events, &t) == 0 ) {
    168                 struct fd_event * ev = t;
    169                 TRACE_DEBUG(FULL, "Found event %d(%p) in queue of peer %p being destroyed", ev->code, ev->data, p);
    170                 free(ev);
    171         }
    172         CHECK_FCT( fd_fifo_del(&p->p_events) );
    173        
    174         CHECK_FCT( fd_thr_term(&p->p_inthr) );
    175         while ( fd_fifo_tryget(p->p_recv, &t) == 0 ) {
    176                 struct msg * m = t;
    177                 TRACE_DEBUG(FULL, "Found message %p in incoming queue of peer %p being destroyed", m, p);
    178                 /* We simply destroy, the remote peer will re-send to someone else...*/
    179                 CHECK_FCT(fd_msg_free(m));
    180         }
    181         CHECK_FCT( fd_fifo_del(&p->p_recv) );
    182        
    183         CHECK_FCT( fd_thr_term(&p->p_outthr) );
    184         while ( fd_fifo_tryget(p->p_tosend, &t) == 0 ) {
    185                 struct msg * m = t;
    186                 TRACE_DEBUG(FULL, "Found message %p in outgoing queue of peer %p being destroyed, requeue", m, p);
    187                 /* We simply requeue in global, the routing thread will re-handle it. */
    188                
    189         }
    190         CHECK_FCT( fd_fifo_del(&p->p_tosend) );
    191        
    192         while (!FD_IS_LIST_EMPTY(&p->p_sentreq)) {
    193                 struct sentreq * sr = (struct sentreq *)(p->p_sentreq.next);
    194                 fd_list_unlink(&sr->chain);
    195                 TRACE_DEBUG(FULL, "Found message %p in list of sent requests to peer %p being destroyed, requeue (fallback)", sr->req, p);
    196                 CHECK_FCT(fd_fifo_post(fd_g_outgoing, &sr->req));
    197                 free(sr);
    198         }
    199        
    200         if (p->p_cnxctx) {
    201                 TODO("destroy p->p_cnxctx");
    202         }
    203        
    204         if (p->p_cb)
    205                 (*p->p_cb)(NULL, p->p_cb_data);
    206        
    207         free(p);
    208        
    209         return 0;
    210 }
    211 
    212 
    21378/* Add a new peer entry */
    21479int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data )
     
    22186       
    22287        /* Create a structure to contain the new peer information */
    223         CHECK_FCT( fd_sp_reinit(&p) );
     88        CHECK_FCT( fd_peer_alloc(&p) );
    22489       
    22590        /* Copy the informations from the parameters received */
     
    248113                        fd_list_insert_before(&p->p_hdr.info.pi_endpoints, li);
    249114                }
    250        
    251         p->p_hdr.info.pi_sec_module = info->pi_sec_module;
    252         memcpy(&p->p_hdr.info.pi_sec_data, &info->pi_sec_data, sizeof(info->pi_sec_data));
    253115       
    254116        /* The internal data */
     
    286148        CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
    287149        if (ret) {
    288                 CHECK_FCT( fd_sp_destroy(&p) );
     150                CHECK_FCT( fd_peer_free(&p) );
    289151        } else {
    290152                CHECK_FCT( fd_psm_begin(p) );
     
    292154        return ret;
    293155}
     156
     157
     158#define free_null( _v )         \
     159        if (_v) {               \
     160                free(_v);       \
     161                (_v) = NULL;    \
     162        }
     163       
     164#define free_list( _l )                                                 \
     165        while (!FD_IS_LIST_EMPTY(_l)) {                                 \
     166                struct fd_list * __li = ((struct fd_list *)(_l))->next; \
     167                fd_list_unlink(__li);                                   \
     168                free(__li);                                             \
     169        }
     170
     171/* Destroy a structure once all cleanups have been performed */
     172int fd_peer_free(struct fd_peer ** ptr)
     173{
     174        struct fd_peer *p;
     175        void * t;
     176       
     177        TRACE_ENTRY("%p", ptr);
     178        CHECK_PARAMS(ptr);
     179        p = *ptr;
     180        *ptr = NULL;
     181        CHECK_PARAMS(p);
     182       
     183        CHECK_PARAMS( FD_IS_LIST_EMPTY(&p->p_hdr.chain) );
     184       
     185        free_null(p->p_hdr.info.pi_diamid);
     186        free_null(p->p_hdr.info.pi_realm);
     187        free_list( &p->p_hdr.info.pi_endpoints );
     188        /* Assume the security data is already freed */
     189        free_null(p->p_hdr.info.pi_prodname);
     190        free_list( &p->p_hdr.info.pi_apps );
     191       
     192        free_null(p->p_dbgorig);
     193        ASSERT(FD_IS_LIST_EMPTY(&p->p_expiry));
     194        ASSERT(FD_IS_LIST_EMPTY(&p->p_actives));
     195       
     196        CHECK_FCT( fd_thr_term(&p->p_psm) );
     197        while ( fd_fifo_tryget(p->p_events, &t) == 0 ) {
     198                struct fd_event * ev = t;
     199                TRACE_DEBUG(FULL, "Found event %d(%p) in queue of peer %p being destroyed", ev->code, ev->data, p);
     200                free(ev);
     201        }
     202        CHECK_FCT( fd_fifo_del(&p->p_events) );
     203       
     204        CHECK_FCT( fd_thr_term(&p->p_inthr) );
     205        while ( fd_fifo_tryget(p->p_recv, &t) == 0 ) {
     206                struct msg * m = t;
     207                TRACE_DEBUG(FULL, "Found message %p in incoming queue of peer %p being destroyed", m, p);
     208                /* We simply destroy, the remote peer will re-send to someone else...*/
     209                CHECK_FCT(fd_msg_free(m));
     210        }
     211        CHECK_FCT( fd_fifo_del(&p->p_recv) );
     212       
     213        CHECK_FCT( fd_thr_term(&p->p_outthr) );
     214        while ( fd_fifo_tryget(p->p_tosend, &t) == 0 ) {
     215                struct msg * m = t;
     216                TRACE_DEBUG(FULL, "Found message %p in outgoing queue of peer %p being destroyed, requeue", m, p);
     217                /* We simply requeue in global, the routing thread will re-handle it. */
     218               
     219        }
     220        CHECK_FCT( fd_fifo_del(&p->p_tosend) );
     221       
     222        while (!FD_IS_LIST_EMPTY(&p->p_sentreq)) {
     223                struct sentreq * sr = (struct sentreq *)(p->p_sentreq.next);
     224                fd_list_unlink(&sr->chain);
     225                TRACE_DEBUG(FULL, "Found message %p in list of sent requests to peer %p being destroyed, requeue (fallback)", sr->req, p);
     226                CHECK_FCT(fd_fifo_post(fd_g_outgoing, &sr->req));
     227                free(sr);
     228        }
     229       
     230        if (p->p_cnxctx) {
     231                TODO("destroy p->p_cnxctx");
     232        }
     233       
     234        if (p->p_cb)
     235                (*p->p_cb)(NULL, p->p_cb_data);
     236       
     237        free(p);
     238       
     239        return 0;
     240}
     241
     242/* Terminate peer module (destroy all peers) */
     243int fd_peer_fini()
     244{
     245        struct fd_list * li;
     246        struct fd_list purge = FD_LIST_INITIALIZER(purge); /* Store zombie peers here */
     247        int list_empty;
     248        struct timespec wait_until, now;
     249       
     250        TRACE_ENTRY();
     251       
     252        CHECK_FCT_DO(fd_p_expi_fini(), /* continue */);
     253       
     254        TRACE_DEBUG(INFO, "Sending terminate signal to all peer connections");
     255       
     256        CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ );
     257        for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     258                struct fd_peer * peer = (struct fd_peer *)li;
     259               
     260                if (peer->p_hdr.info.pi_state != STATE_ZOMBIE) {
     261                        CHECK_FCT_DO( fd_psm_terminate(peer), /* continue */ );
     262                } else {
     263                        li = li->prev; /* to avoid breaking the loop */
     264                        fd_list_unlink(&peer->p_hdr.chain);
     265                        fd_list_insert_before(&purge, &peer->p_hdr.chain);
     266                }
     267        }
     268        list_empty = FD_IS_LIST_EMPTY(&fd_g_peers);
     269        CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
     270       
     271        if (!list_empty) {
     272                CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &now)  );
     273                TRACE_DEBUG(INFO, "Waiting for connections shutdown... (%d sec max)", DPR_TIMEOUT);
     274                wait_until.tv_sec  = now.tv_sec + DPR_TIMEOUT;
     275                wait_until.tv_nsec = now.tv_nsec;
     276        }
     277       
     278        while ((!list_empty) && (TS_IS_INFERIOR(&now, &wait_until))) {
     279               
     280                /* Allow the PSM(s) to execute */
     281                pthread_yield();
     282               
     283                /* Remove zombie peers */
     284                CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ );
     285                for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     286                        struct fd_peer * peer = (struct fd_peer *)li;
     287                        if (peer->p_hdr.info.pi_state == STATE_ZOMBIE) {
     288                                li = li->prev; /* to avoid breaking the loop */
     289                                fd_list_unlink(&peer->p_hdr.chain);
     290                                fd_list_insert_before(&purge, &peer->p_hdr.chain);
     291                        }
     292                }
     293                list_empty = FD_IS_LIST_EMPTY(&fd_g_peers);
     294                CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
     295        }
     296       
     297        if (!list_empty) {
     298                TRACE_DEBUG(INFO, "Forcing connections shutdown");
     299                CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ );
     300                while (!FD_IS_LIST_EMPTY(&fd_g_peers)) {
     301                        struct fd_peer * peer = (struct fd_peer *)(fd_g_peers.next);
     302                        fd_psm_abord(peer);
     303                        fd_list_unlink(&peer->p_hdr.chain);
     304                        fd_list_insert_before(&purge, &peer->p_hdr.chain);
     305                }
     306                CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
     307        }
     308       
     309        /* Free memory objects of all peers */
     310        while (!FD_IS_LIST_EMPTY(&purge)) {
     311                struct fd_peer * peer = (struct fd_peer *)(purge.next);
     312                fd_list_unlink(&peer->p_hdr.chain);
     313                fd_peer_free(&peer);
     314        }
     315       
     316        return 0;
     317}
     318
     319/* Dump info of one peer */
     320void fd_peer_dump(struct fd_peer * peer, int details)
     321{
     322        if (peer->p_eyec != EYEC_PEER) {
     323                fd_log_debug("  Invalid peer @ %p !\n", peer);
     324                return;
     325        }
     326
     327        fd_log_debug(">  %s\t%s", STATE_STR(peer->p_hdr.info.pi_state), peer->p_hdr.info.pi_diamid);
     328        if (details > INFO) {
     329                fd_log_debug("\t(rlm:%s)", peer->p_hdr.info.pi_realm);
     330                if (peer->p_hdr.info.pi_prodname)
     331                        fd_log_debug("\t['%s' %u]", peer->p_hdr.info.pi_prodname, peer->p_hdr.info.pi_firmrev);
     332        }
     333        fd_log_debug("\n");
     334        if (details > FULL) {
     335                /* Dump all info */
     336                fd_log_debug("\tEntry origin : %s\n", peer->p_dbgorig);
     337                fd_log_debug("\tFlags : %s%s%s%s%s - %s%s%s\n",
     338                                peer->p_hdr.info.pi_flags.pro3 == PI_P3_DEFAULT ? "" :
     339                                        (peer->p_hdr.info.pi_flags.pro3 == PI_P3_IP ? "IP." : "IPv6."),
     340                                peer->p_hdr.info.pi_flags.pro4 == PI_P4_DEFAULT ? "" :
     341                                        (peer->p_hdr.info.pi_flags.pro4 == PI_P4_TCP ? "TCP." : "SCTP."),
     342                                peer->p_hdr.info.pi_flags.alg ? "PrefTCP." : "",
     343                                peer->p_hdr.info.pi_flags.sec == PI_SEC_DEFAULT ? "" :
     344                                        (peer->p_hdr.info.pi_flags.sec == PI_SEC_NONE ? "IPSec." : "InbandTLS."),
     345                                peer->p_hdr.info.pi_flags.exp ? "Expire." : "",
     346                                peer->p_hdr.info.pi_flags.inband & PI_INB_NONE ? "InbandIPsecOK." : "",
     347                                peer->p_hdr.info.pi_flags.inband & PI_INB_TLS ?  "InbandTLSOK." : "",
     348                                peer->p_hdr.info.pi_flags.relay ? "Relay (0xffffff)" : "No relay"
     349                                );
     350                fd_log_debug("\tLifetime : %d sec\n", peer->p_hdr.info.pi_lft);
     351               
     352                TODO("Dump remaining useful information");
     353        }
     354}
     355
     356/* Dump the list of peers */
     357void fd_peer_dump_list(int details)
     358{
     359        struct fd_list * li;
     360       
     361        fd_log_debug("Dumping list of peers :\n");
     362        CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ );
     363       
     364        for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     365                struct fd_peer * np = (struct fd_peer *)li;
     366                fd_peer_dump(np, details);
     367        }
     368       
     369        CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
     370}
     371
Note: See TracChangeset for help on using the changeset viewer.