Navigation


Changeset 14:14cf6daf716d in freeDiameter


Ignore:
Timestamp:
Oct 1, 2009, 6:24:07 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Some progress on peers module

Files:
15 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/extensions.c

    r10 r14  
    5050
    5151/* list of extensions */
    52 static struct fd_list ext_list;
    53 
    54 /* Initialize the module */
    55 int fd_ext_init()
    56 {
    57         TRACE_ENTRY();
    58         fd_list_init(&ext_list, NULL);
    59         return 0;
    60 }
     52static struct fd_list ext_list = FD_LIST_INITIALIZER(ext_list);
    6153
    6254/* Add new extension */
  • freeDiameter/fD.h

    r13 r14  
    4242#include <freeDiameter/freeDiameter.h>
    4343
     44/* Timeout for establishing a connection */
     45#ifndef CNX_TIMEOUT
     46#define  CNX_TIMEOUT    10      /* in seconds */
     47#endif /* CNX_TIMEOUT */
     48
     49/* Timeout for receiving a CER after incoming connection is established */
     50#ifndef INCNX_TIMEOUT
     51#define  INCNX_TIMEOUT   20     /* in seconds */
     52#endif /* INCNX_TIMEOUT */
     53
     54/* Timeout for receiving a CEA after CER is sent */
     55#ifndef CEA_TIMEOUT
     56#define  CEA_TIMEOUT    10      /* in seconds */
     57#endif /* CEA_TIMEOUT */
     58
     59/* The timeout value to wait for answer to a DPR */
     60#ifndef DPR_TIMEOUT
     61#define DPR_TIMEOUT     15      /* in seconds */
     62#endif /* DPR_TIMEOUT */
     63
    4464/* Configuration */
    4565int fd_conf_init();
     
    4969
    5070/* Extensions */
    51 int fd_ext_init();
    5271int fd_ext_add( char * filename, char * conffile );
    5372int fd_ext_load();
     
    82101        char            *p_dbgorig;
    83102       
    84         /* Mutex that protect this peer structure */
    85         pthread_mutex_t  p_mtx;
    86        
    87         /* Reference counter -- freed only when this reaches 0 */
    88         unsigned         p_refcount;
    89        
    90103        /* Chaining in peers sublists */
     104        struct fd_list   p_actives;     /* list of peers in the STATE_OPEN state -- faster routing creation */
    91105        struct fd_list   p_expiry;      /* list of expiring peers, ordered by their timeout value */
    92         struct fd_list   p_actives;     /* list of peers in the STATE_OPEN state -- faster routing creation */
    93        
    94         /* The next hop-by-hop id value for the link */
    95         uint32_t         p_hbh;
     106        struct timespec  p_exp_timer;   /* Timestamp where the peer will expire; updated each time activity is seen on the peer (except DW) */
    96107       
    97108        /* Some flags influencing the peer state machine */
     
    109120       
    110121        /* The events queue, peer state machine thread, timer for states timeouts */
    111         struct fifo     *p_events;
     122        struct fifo     *p_events;      /* The mutex of this FIFO list protects also the state and timer information */
    112123        pthread_t        p_psm;
    113124        struct timespec  p_psm_timer;
     
    121132        pthread_t        p_outthr;
    122133       
     134        /* The next hop-by-hop id value for the link, only read & modified by p_outthr */
     135        uint32_t         p_hbh;
     136       
    123137        /* Sent requests (for fallback), list of struct sentreq ordered by hbh */
    124138        struct fd_list   p_sentreq;
    125139       
    126         /* connection context: socket & other metadata */
     140        /* connection context: socket, callbacks and so on */
    127141        struct cnxctx   *p_cnxctx;
    128142       
     
    145159        /* A message was received in the peer */
    146160        ,FDEVP_MSG_INCOMING
     161       
     162        /* The PSM state is expired */
     163        ,FDEVP_PSM_TIMEOUT
    147164};
     165const char * fd_pev_str(int event);
    148166
    149167/* Structure to store a sent request */
     
    154172
    155173/* Functions */
    156 int fd_peer_init();
    157174int fd_peer_fini();
    158175void fd_peer_dump_list(int details);
    159176/* fd_peer_add declared in freeDiameter.h */
    160 int fd_peer_rc_decr(struct fd_peer **ptr, int locked);
    161177
    162178/* Peer expiry */
    163179int fd_p_expi_init(void);
    164180int fd_p_expi_fini(void);
    165 int fd_p_expi_update(struct fd_peer * peer, int locked );
    166 int fd_p_expi_unlink(struct fd_peer * peer, int locked );
     181int fd_p_expi_update(struct fd_peer * peer );
    167182
    168183/* Peer state machine */
  • freeDiameter/fdd.y

    r13 r14  
    315315connpeer:               {
    316316                                memset(&fddpi, 0, sizeof(fddpi));
     317                                fd_list_init( &fddpi.pi_endpoints, NULL );
     318                                fd_list_init( &fddpi.pi_apps, NULL );
    317319                        }
    318320                        CONNPEER '=' QSTRING peerinfo ';'
  • freeDiameter/main.c

    r13 r14  
    4242static void * sig_hdl(void * arg);
    4343static int main_cmdline(int argc, char *argv[]);
     44static void main_version(void);
     45static void main_help( void );
    4446
    4547/* The static configuration structure */
     
    7779       
    7880        /* Initialize other modules */
    79         CHECK_FCT(  fd_ext_init()  );
    8081        CHECK_FCT(  fd_queues_init()  );
    8182        CHECK_FCT(  fd_msg_init()  );
    82         CHECK_FCT(  fd_peer_init()  );
     83        CHECK_FCT(  fd_p_expi_init()  );
    8384       
    8485        /* Parse the configuration file */
     
    133134       
    134135        /* cleanups */
    135         CHECK_FCT_DO( fd_ext_fini(), /* continue */ );
     136        TODO("Stop dispatch thread(s) properly (no cancel yet)");
     137        CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ );
     138        TODO("Stop dispatch & routing threads");
     139        CHECK_FCT_DO( fd_ext_fini(), /* Cleaup all extensions */ );
     140        TODO("Cleanup queues (dump all remaining messages ?)");
     141       
    136142        CHECK_FCT_DO( fd_thr_term(&sig_th), /* continue */ );
    137143       
    138144        return ret;
     145}
     146
     147const char * fd_ev_str(int event)
     148{
     149        switch (event) {
     150        #define case_str( _val )\
     151                case _val : return #_val
     152                case_str(FDEV_TERMINATE);
     153                case_str(FDEV_DUMP_DICT);
     154                case_str(FDEV_DUMP_EXT);
     155                case_str(FDEV_DUMP_QUEUES);
     156                case_str(FDEV_DUMP_CONFIG);
     157                case_str(FDEV_DUMP_PEERS);
     158               
     159                default:
     160                        TRACE_DEBUG(FULL, "Unknown event : %d", event);
     161                        return "Unknown event";
     162        }
     163}
     164
     165/* Parse the command-line */
     166static int main_cmdline(int argc, char *argv[])
     167{
     168        int c;
     169        int option_index = 0;
     170       
     171        struct option long_options[] = {
     172                { "help",       0, NULL, 'h' },
     173                { "version",    0, NULL, 'V' },
     174                { "config",     1, NULL, 'c' },
     175                { "debug",      0, NULL, 'd' },
     176                { "quiet",      0, NULL, 'q' },
     177                { NULL, 0, NULL, 0 }
     178        };
     179       
     180        TRACE_ENTRY("%d %p", argc, argv);
     181       
     182        /* Loop on arguments */
     183        while (1) {
     184                c = getopt_long (argc, argv, "hVc:dq", long_options, &option_index);
     185                if (c == -1)
     186                        break;  /* Exit from the loop.  */
     187               
     188                switch (c) {
     189                        case 'h':       /* Print help and exit.  */
     190                                main_help();
     191                                exit(0);
     192
     193                        case 'V':       /* Print version and exit.  */
     194                                main_version();
     195                                exit(0);
     196
     197                        case 'c':       /* Read configuration from this file instead of the default location..  */
     198                                CHECK_PARAMS( optarg );
     199                                fd_g_config->cnf_file = optarg;
     200                                break;
     201
     202                        case 'd':       /* Increase verbosity of debug messages.  */
     203                                fd_g_debug_lvl++;
     204                                break;
     205                               
     206                        case 'q':       /* Decrease verbosity then remove debug messages.  */
     207                                fd_g_debug_lvl--;
     208                                break;
     209
     210                        case '?':       /* Invalid option.  */
     211                                /* `getopt_long' already printed an error message.  */
     212                                TRACE_DEBUG(INFO, "getopt_long found an invalid character\n");
     213                                return EINVAL;
     214
     215                        default:        /* bug: option not considered.  */
     216                                TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c\n", c);
     217                                ASSERT(0);
     218                                return EINVAL;
     219                }
     220        }
     221               
     222        return 0;
    139223}
    140224
     
    187271}
    188272
    189 /* Parse the command-line */
    190 static int main_cmdline(int argc, char *argv[])
    191 {
    192         int c;
    193         int option_index = 0;
    194        
    195         struct option long_options[] = {
    196                 { "help",       0, NULL, 'h' },
    197                 { "version",    0, NULL, 'V' },
    198                 { "config",     1, NULL, 'c' },
    199                 { "debug",      0, NULL, 'd' },
    200                 { "quiet",      0, NULL, 'q' },
    201                 { NULL, 0, NULL, 0 }
    202         };
    203        
    204         TRACE_ENTRY("%d %p", argc, argv);
    205        
    206         /* Loop on arguments */
    207         while (1) {
    208                 c = getopt_long (argc, argv, "hVc:dq", long_options, &option_index);
    209                 if (c == -1)
    210                         break;  /* Exit from the loop.  */
    211                
    212                 switch (c) {
    213                         case 'h':       /* Print help and exit.  */
    214                                 main_help();
    215                                 exit(0);
    216 
    217                         case 'V':       /* Print version and exit.  */
    218                                 main_version();
    219                                 exit(0);
    220 
    221                         case 'c':       /* Read configuration from this file instead of the default location..  */
    222                                 CHECK_PARAMS( optarg );
    223                                 fd_g_config->cnf_file = optarg;
    224                                 break;
    225 
    226                         case 'd':       /* Increase verbosity of debug messages.  */
    227                                 fd_g_debug_lvl++;
    228                                 break;
    229                                
    230                         case 'q':       /* Decrease verbosity then remove debug messages.  */
    231                                 fd_g_debug_lvl--;
    232                                 break;
    233 
    234                         case '?':       /* Invalid option.  */
    235                                 /* `getopt_long' already printed an error message.  */
    236                                 TRACE_DEBUG(INFO, "getopt_long found an invalid character\n");
    237                                 return EINVAL;
    238 
    239                         default:        /* bug: option not considered.  */
    240                                 TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c\n", c);
    241                                 ASSERT(0);
    242                                 return EINVAL;
    243                 }
    244         }
    245                
    246         return 0;
    247        
    248 }
    249 
    250273#ifdef HAVE_SIGNALENT_H
    251274const char *const signalstr[] = {
  • freeDiameter/p_expiry.c

    r13 r14  
    3636#include "fD.h"
    3737
     38static pthread_t       exp_thr;
     39static struct fd_list  exp_list = FD_LIST_INITIALIZER( exp_list );
     40static pthread_cond_t  exp_cnd  = PTHREAD_COND_INITIALIZER;
     41static pthread_mutex_t exp_mtx  = PTHREAD_MUTEX_INITIALIZER;
    3842
     43static void * exp_th_fct(void * arg)
     44{
     45        fd_log_threadname ( "Peers/expire" );
     46        TRACE_ENTRY( "" );
     47       
     48        CHECK_POSIX_DO( pthread_mutex_lock(&exp_mtx),  goto error );
     49        pthread_cleanup_push( fd_cleanup_mutex, &exp_mtx );
     50       
     51        do {
     52                struct timespec now;
     53                struct fd_peer * first;
     54               
     55                /* Check if there are expiring sessions available */
     56                if (FD_IS_LIST_EMPTY(&exp_list)) {
     57                        /* Just wait for a change or cancelation */
     58                        CHECK_POSIX_DO( pthread_cond_wait( &exp_cnd, &exp_mtx ), goto error );
     59                        /* Restart the loop on wakeup */
     60                        continue;
     61                }
     62               
     63                /* Get the pointer to the peer that expires first */
     64                first = (struct fd_peer *)(exp_list.next->o);
     65                ASSERT( CHECK_PEER(first) );
     66               
     67                /* Get the current time */
     68                CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now),  goto error  );
    3969
     70                /* If first peer is not expired, we just wait until it happens */
     71                if ( TS_IS_INFERIOR( &now, &first->p_exp_timer ) ) {
     72                       
     73                        CHECK_POSIX_DO2(  pthread_cond_timedwait( &exp_cnd, &exp_mtx, &first->p_exp_timer ), 
     74                                        ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */,
     75                                        /* on other error, */ goto error );
     76       
     77                        /* on wakeup, loop */
     78                        continue;
     79                }
     80               
     81                /* Now, the first peer in the list is expired; signal it */
     82                fd_list_unlink( &first->p_expiry );
     83                CHECK_FCT_DO( fd_event_send(first->p_events, FDEVP_TERMINATE, NULL), goto error );
     84               
     85        } while (1);
     86       
     87        pthread_cleanup_pop( 1 );
     88error:
     89        TRACE_DEBUG(INFO, "An error occurred in peers module! Expiry thread is terminating...");
     90        ASSERT(0);
     91        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
     92        return NULL;
     93}
    4094
    4195/* Initialize peers expiry mechanism */
    4296int fd_p_expi_init(void)
    4397{
    44         TODO("");
    45         return ENOTSUP;
     98        TRACE_ENTRY();
     99        CHECK_FCT( pthread_create( &exp_thr, NULL, exp_th_fct, NULL ) );
     100        return 0;
    46101}
    47102
     
    49104int fd_p_expi_fini(void)
    50105{
    51         TODO("");
    52         return ENOTSUP;
     106        CHECK_FCT_DO( fd_thr_term(&exp_thr), );
     107        CHECK_POSIX( pthread_mutex_lock(&exp_mtx) );
     108       
     109        while (!FD_IS_LIST_EMPTY(&exp_list)) {
     110                struct fd_peer * peer = (struct fd_peer *)(exp_list.next->o);
     111                fd_list_unlink(&peer->p_expiry );
     112        }
     113       
     114        CHECK_POSIX( pthread_mutex_unlock(&exp_mtx) );
     115        return 0;
    53116}
    54117
    55 /* Add a peer in the expiry list if needed */
    56 int fd_p_expi_update(struct fd_peer * peer, int locked )
     118/* Add / requeue a peer in the expiry list */
     119int fd_p_expi_update(struct fd_peer * peer )
    57120{
    58         TODO("");
     121        TRACE_ENTRY("%p", peer);
     122        CHECK_PARAMS( CHECK_PEER(peer) );
     123       
     124        CHECK_POSIX( pthread_mutex_lock(&exp_mtx) );
     125       
     126        fd_list_unlink(&peer->p_expiry );
    59127       
    60128        /* if peer expires */
    61                 /* add to the expiry list in appropriate position */
    62                 /* increment peer refcount */
     129        if (peer->p_hdr.info.pi_flags.exp) {
     130                struct fd_list * li;
     131               
     132                /* update the p_exp_timer value */
     133                CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &peer->p_exp_timer)  );
     134                peer->p_exp_timer.tv_sec += peer->p_hdr.info.pi_lft;
     135               
     136                /* add to the expiry list in appropriate position (probably around the end) */
     137                for (li = exp_list.prev; li != &exp_list; li = li->prev) {
     138                        struct fd_peer * p = (struct fd_peer *)(li->o);
     139                        if (TS_IS_INFERIOR( &p->p_exp_timer, &peer->p_exp_timer ) )
     140                                break;
     141                }
     142               
     143                fd_list_insert_after(li, &peer->p_expiry);
     144               
    63145                /* signal the expiry thread if we added in first position */
     146                if (li == &exp_list) {
     147                        CHECK_POSIX( pthread_cond_signal(&exp_cnd) );
     148                }
     149        }
    64150       
    65         return ENOTSUP;
     151        CHECK_POSIX( pthread_mutex_unlock(&exp_mtx) );
     152        return 0;
    66153}
    67154
    68 /* Remove a peer from expiry list if needed */
    69 int fd_p_expi_unlink(struct fd_peer * peer, int locked )
    70 {
    71         TODO("");
    72         /* if peer is in expiry list */
    73                 /* remove from the list */
    74                 /* decrement peer refcount */
    75                 /* no need to signal the expiry thread ... */
    76        
    77         return ENOTSUP;
    78 }
  • freeDiameter/p_psm.c

    r13 r14  
    3636#include "fD.h"
    3737
     38const char *peer_state_str[] = {
     39          "STATE_ZOMBIE"
     40        , "STATE_OPEN"
     41        , "STATE_CLOSED"
     42        , "STATE_CLOSING"
     43        , "STATE_WAITCNXACK"
     44        , "STATE_WAITCNXACK_ELEC"
     45        , "STATE_WAITCEA"
     46        , "STATE_SUSPECT"
     47        , "STATE_REOPEN"
     48        };
     49
     50const char * fd_pev_str(int event)
     51{
     52        switch (event) {
     53        #define case_str( _val )\
     54                case _val : return #_val
     55                case_str(FDEVP_TERMINATE);
     56                case_str(FDEVP_DUMP_ALL);
     57                case_str(FDEVP_MSG_INCOMING);
     58                case_str(FDEVP_PSM_TIMEOUT);
     59               
     60                default:
     61                        TRACE_DEBUG(FULL, "Unknown event : %d", event);
     62                        return "Unknown event";
     63        }
     64}
     65
     66
    3867static int started = 0;
    3968static pthread_mutex_t  started_mtx = PTHREAD_MUTEX_INITIALIZER;
     
    5685}
    5786
     87/* Cancelation cleanup : set ZOMBIE state in the peer */
     88void cleanup_state(void * arg)
     89{
     90        struct fd_peer * peer = (struct fd_peer *)arg;
     91        CHECK_PARAMS_DO( CHECK_PEER(peer), return );
     92        peer->p_hdr.info.pi_state = STATE_ZOMBIE;
     93        return;
     94}
     95
     96/* Set timeout timer of next event */
     97static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
     98{
     99        /* Initialize the timer */
     100        CHECK_POSIX_DO(  clock_gettime( CLOCK_REALTIME,  &peer->p_psm_timer ), ASSERT(0) );
     101       
     102        if (add_random) {
     103                if (delay > 2)
     104                        delay -= 2;
     105                else
     106                        delay = 0;
     107
     108                /* Add a random value between 0 and 4sec */
     109                peer->p_psm_timer.tv_sec += random() % 4;
     110                peer->p_psm_timer.tv_nsec+= random() % 1000000000L;
     111                if (peer->p_psm_timer.tv_nsec > 1000000000L) {
     112                        peer->p_psm_timer.tv_nsec -= 1000000000L;
     113                        peer->p_psm_timer.tv_sec ++;
     114                }
     115        }
     116       
     117        peer->p_psm_timer.tv_sec += delay;
     118       
     119#if 0
     120        /* temporary for debug */
     121        peer->p_psm_timer.tv_sec += 10;
     122#endif
     123}
     124
     125static int psm_ev_timedget(struct fd_peer * peer, int *code, void ** data)
     126{
     127        struct fd_event * ev;
     128        int ret = 0;
     129       
     130        TRACE_ENTRY("%p %p %p", peer, code, data);
     131       
     132        ret = fd_fifo_timedget(peer->p_events, &ev, &peer->p_psm_timer);
     133        if (ret == ETIMEDOUT) {
     134                *code = FDEVP_PSM_TIMEOUT;
     135                *data = NULL;
     136        } else {
     137                CHECK_FCT( ret );
     138                *code = ev->code;
     139                *data = ev->data;
     140                free(ev);
     141        }
     142       
     143        return 0;
     144}       
     145
     146/* The state machine thread */
     147static void * p_psm_th( void * arg )
     148{
     149        struct fd_peer * peer = (struct fd_peer *)arg;
     150        int created_started = started;
     151       
     152        CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) );
     153       
     154        pthread_cleanup_push( cleanup_state, arg );
     155       
     156        /* Set the thread name */
     157        {
     158                char buf[48];
     159                sprintf(buf, "PSM/%.*s", sizeof(buf) - 5, peer->p_hdr.info.pi_diamid);
     160                fd_log_threadname ( buf );
     161        }
     162       
     163        /* Wait that the PSM are authorized to start in the daemon */
     164        CHECK_FCT_DO( fd_psm_waitstart(), goto end );
     165       
     166        /* The state machine starts in CLOSED state */
     167        peer->p_hdr.info.pi_state = STATE_CLOSED;
     168       
     169        /* Initialize the timer */
     170        if (peer->p_flags.pf_responder) {
     171                psm_next_timeout(peer, 0, INCNX_TIMEOUT);
     172        } else {
     173                psm_next_timeout(peer, created_started ? 0 : 1, 0);
     174        }
     175       
     176psm:
     177        do {
     178                int event;
     179                void * ev_data;
     180               
     181                /* Get next event */
     182                CHECK_FCT_DO( psm_ev_timedget(peer, &event, &ev_data), goto end );
     183                TRACE_DEBUG(FULL, "'%s'\t<-- '%s'\t(%p)\t'%s'",
     184                                STATE_STR(peer->p_hdr.info.pi_state),
     185                                fd_pev_str(event), ev_data,
     186                                peer->p_hdr.info.pi_diamid);
     187               
     188                /* Now, the action depends on the current state and the incoming event */
     189               
     190       
     191        } while (1);   
     192       
     193       
     194end:   
     195        /* set STATE_ZOMBIE */
     196        pthread_cleanup_pop(1);
     197        return NULL;
     198}       
     199       
     200       
     201
     202
     203/* Create the PSM thread of one peer structure */
     204int fd_psm_begin(struct fd_peer * peer )
     205{
     206        TRACE_ENTRY("%p", peer);
     207        TODO("");
     208        return ENOTSUP;
     209}
     210
     211/* End the PSM (clean ending) */
     212int fd_psm_terminate(struct fd_peer * peer )
     213{
     214        TRACE_ENTRY("%p", peer);
     215        CHECK_PARAMS( CHECK_PEER(peer) );
     216        CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, NULL) );
     217        return 0;
     218}
     219
     220/* End the PSM violently */
     221void fd_psm_abord(struct fd_peer * peer )
     222{
     223        TRACE_ENTRY("%p", peer);
     224        TODO("Cancel PSM thread");
     225        TODO("Cancel IN thread");
     226        TODO("Cancel OUT thread");
     227        TODO("Cleanup the connection");
     228        return;
     229}
     230
    58231/* Allow the state machines to start */
    59232int fd_psm_start()
     
    67240}
    68241
    69 /* Create the PSM thread of one peer structure */
    70 int fd_psm_begin(struct fd_peer * peer )
    71 {
    72         TRACE_ENTRY("%p", peer);
    73         TODO("");
    74         return ENOTSUP;
    75 }
    76 
    77 /* End the PSM (clean ending) */
    78 int fd_psm_terminate(struct fd_peer * peer )
    79 {
    80         TRACE_ENTRY("%p", peer);
    81         TODO("");
    82         return ENOTSUP;
    83 }
    84 
    85 /* End the PSM violently */
    86 void fd_psm_abord(struct fd_peer * peer )
    87 {
    88         TRACE_ENTRY("%p", peer);
    89         TODO("");
    90         return;
    91 }
    92 
  • freeDiameter/peers.c

    r13 r14  
    3636#include "fD.h"
    3737
    38 const char *peer_state_str[] = { "<error>"
    39         , "STATE_DISABLED"
    40         , "STATE_OPEN"
    41         , "STATE_CLOSED"
    42         , "STATE_CLOSING"
    43         , "STATE_WAITCNXACK"
    44         , "STATE_WAITCNXACK_ELEC"
    45         , "STATE_WAITCEA"
    46         , "STATE_SUSPECT"
    47         , "STATE_REOPEN"
    48         };
    49 
    50 struct fd_list   fd_g_peers;
    51 pthread_rwlock_t fd_g_peers_rw;
    52 
    53 /* Initialize the peers list */
    54 int fd_peer_init()
    55 {
    56         TRACE_ENTRY();
    57        
    58         fd_list_init(&fd_g_peers, NULL);
    59         CHECK_POSIX( pthread_rwlock_init(&fd_g_peers_rw, NULL) );
    60        
    61         CHECK_FCT(fd_p_expi_init());
    62        
    63         return 0;
    64 }
     38struct fd_list   fd_g_peers = FD_LIST_INITIALIZER(fd_g_peers);
     39pthread_rwlock_t fd_g_peers_rw = PTHREAD_RWLOCK_INITIALIZER;
    6540
    6641/* Terminate peer module (destroy all peers) */
    6742int fd_peer_fini()
    6843{
     44        struct fd_list * li;
    6945        TRACE_ENTRY();
    7046       
    7147        CHECK_FCT_DO(fd_p_expi_fini(), /* continue */);
    7248       
    73         TODO("Complete this function")
     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 ) */
    7461       
    7562        return 0;
     
    125112       
    126113        fd_list_init(&p->p_hdr.info.pi_endpoints, NULL);
    127         p->p_hdr.info.pi_state = STATE_DISABLED;
    128114        fd_list_init(&p->p_hdr.info.pi_apps, NULL);
    129115       
    130116        p->p_eyec = EYEC_PEER;
    131         CHECK_POSIX( pthread_mutex_init(&p->p_mtx, NULL) );
    132117        fd_list_init(&p->p_expiry, p);
    133118        fd_list_init(&p->p_actives, p);
     
    166151        CHECK_PARAMS(p);
    167152       
    168         CHECK_PARAMS( (p->p_refcount == 0) && FD_IS_LIST_EMPTY(&p->p_hdr.chain) );
     153        CHECK_PARAMS( FD_IS_LIST_EMPTY(&p->p_hdr.chain) );
    169154       
    170155        free_null(p->p_hdr.info.pi_diamid);
     
    176161       
    177162        free_null(p->p_dbgorig);
    178         CHECK_POSIX( pthread_mutex_destroy(&p->p_mtx) );
    179163        ASSERT(FD_IS_LIST_EMPTY(&p->p_expiry));
    180164        ASSERT(FD_IS_LIST_EMPTY(&p->p_actives));
     
    214198        }
    215199       
    216         TRACE_DEBUG(NONE, "TODO: destroy p->p_cnxctx here");
     200        if (p->p_cnxctx) {
     201                TODO("destroy p->p_cnxctx");
     202        }
    217203       
    218204        if (p->p_cb)
     
    224210}
    225211
    226 /* Decrement refcount, delete if 0 */
    227 int fd_peer_rc_decr(struct fd_peer **ptr, int locked)
    228 {
    229         int count;
    230         struct fd_peer *p;
    231         TRACE_ENTRY("%p %d", p, locked);
    232        
    233         CHECK_PARAMS(ptr && CHECK_PEER( *ptr ));
    234         p = *ptr;
    235        
    236         if (!locked) {
    237                 CHECK_POSIX( pthread_rwlock_rdlock(&fd_g_peers_rw) );
    238                 CHECK_POSIX( pthread_mutex_lock( &p->p_mtx ) );
    239                 CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
    240         }
    241        
    242         count = --(p->p_refcount);
    243        
    244         if (!locked) {
    245                 CHECK_POSIX( pthread_mutex_unlock( &p->p_mtx ) );
    246         }
    247        
    248         if (count <= 0) {
    249                 /* All links have already been removed, we can destroy */
    250                 CHECK_FCT( fd_sp_destroy(ptr) );
    251         }
    252         return 0;
    253 }
    254212
    255213/* Add a new peer entry */
     
    284242       
    285243        /* Move the items from one list to the other */
    286         while (!FD_IS_LIST_EMPTY( &info->pi_endpoints ) ) {
    287                 li = info->pi_endpoints.next;
    288                 fd_list_unlink(li);
    289                 fd_list_insert_before(&p->p_hdr.info.pi_endpoints, li);
    290         }
     244        if (info->pi_endpoints.next)
     245                while (!FD_IS_LIST_EMPTY( &info->pi_endpoints ) ) {
     246                        li = info->pi_endpoints.next;
     247                        fd_list_unlink(li);
     248                        fd_list_insert_before(&p->p_hdr.info.pi_endpoints, li);
     249                }
    291250       
    292251        p->p_hdr.info.pi_sec_module = info->pi_sec_module;
     
    304263        /* Ok, now check if we don't already have an entry with the same Diameter Id, and insert this one */
    305264        CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) );
    306         CHECK_POSIX( pthread_mutex_lock( &p->p_mtx ) );
    307265       
    308266        for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     
    319277        if (! ret) {
    320278                /* Update expiry list */
    321                 CHECK_FCT_DO( ret = fd_p_expi_update( p, 1 ), goto out );
     279                CHECK_FCT_DO( ret = fd_p_expi_update( p ), goto out );
    322280               
    323281                /* Insert the new element in the list */
    324282                fd_list_insert_before( li, &p->p_hdr.chain );
    325                 p->p_refcount++;
    326283        }
    327284
    328285out:   
    329         CHECK_POSIX( pthread_mutex_unlock( &p->p_mtx ) );
    330286        CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
    331287        if (ret) {
    332288                CHECK_FCT( fd_sp_destroy(&p) );
    333289        } else {
    334                 CHECK_FCT( fd_psm_start(p) );
     290                CHECK_FCT( fd_psm_begin(p) );
    335291        }
    336292        return ret;
  • include/freeDiameter/freeDiameter.h

    r13 r14  
    141141        ,FDEV_DUMP_PEERS        /* Dump the list of peers */
    142142};
    143 
     143const char * fd_ev_str(int event);
    144144
    145145
     
    151151enum peer_state {
    152152        /* Stable states */
    153         STATE_DISABLED = 1,     /* No connexion must be attempted / only this state means that the peer PSM thread is not running */
     153        STATE_ZOMBIE = 0,       /* The threads handling the peer are not running for some reason */
    154154        STATE_OPEN,             /* Connexion established */
    155155       
     
    167167        /* Failover state machine */
    168168        STATE_SUSPECT,          /* A DWR was sent and not answered within TwTime. Failover in progress. */
    169         STATE_REOPEN            /* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */
     169        STATE_REOPEN,           /* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */
    170170};
    171171extern const char *peer_state_str[];
    172172#define STATE_STR(state) \
    173         peer_state_str[ ((unsigned)(state)) <= STATE_REOPEN ? ((unsigned)(state)) : 0 ]
     173        (((unsigned)(state)) <= STATE_REOPEN ? peer_state_str[((unsigned)(state)) ] : "<Invalid>")
    174174
    175175/* Information about a remote peer. Same structure is used for creating a new entry, but not all fields are meaningful in that case */
     
    238238        }               pi_sec_data;
    239239       
    240         /* The remaining information is read-only, not used for peer creation */
     240        /* The remaining information must not be modified, and is not used for peer creation */
    241241        enum peer_state pi_state;
    242242        uint32_t        pi_vendorid;    /* Content of the Vendor-Id AVP, or 0 by default */
  • include/freeDiameter/libfreeDiameter.h

    r13 r14  
    193193#ifndef ERRORS_ON_TODO
    194194#define TODO( _msg, _args... ) \
    195         TRACE_DEBUG(NONE, _msg , ##_args);
     195        TRACE_DEBUG(NONE, "TODO: " _msg , ##_args);
    196196#else /* ERRORS_ON_TODO */
    197197#define TODO( _msg, _args... ) \
     
    446446};
    447447
    448 #define FD_LIST( _li ) ((struct fd_list *)( _li ))
    449 
    450448/* Initialize a list element */
     449#define FD_LIST_INITIALIZER( _list_name ) \
     450        { .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = NULL }
     451#define FD_LIST_INITIALIZER_O( _list_name, _obj ) \
     452        { .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = _obj }
    451453void fd_list_init ( struct fd_list * list, void *obj );
    452454
    453455/* Return boolean, true if the list is empty */
    454 #define FD_IS_LIST_EMPTY( _list ) (((FD_LIST(_list))->head == (_list)) && ((FD_LIST(_list))->next == (_list)))
     456#define FD_IS_LIST_EMPTY( _list ) ((((struct fd_list *)(_list))->head == (_list)) && (((struct fd_list *)(_list))->next == (_list)))
    455457
    456458/* Insert an item in a list at known position */
  • libfreeDiameter/dispatch.c

    r7 r14  
    4444
    4545/* List of all registered handlers -- useful if we want to cleanup properly at some point... */
    46 static struct fd_list all_handlers;
     46static struct fd_list all_handlers = FD_LIST_INITIALIZER( all_handlers );
    4747
    4848/* List of handlers registered for DISP_HOW_ANY. Other handlers are stored in the dictionary */
    49 static struct fd_list any_handlers;
     49static struct fd_list any_handlers = FD_LIST_INITIALIZER( any_handlers );
    5050
    5151/* The structure to store a callback */
     
    6464
    6565/**************************************************************************************/
    66 /* Initialize the module lists */
    67 void fd_disp_init(void)
    68 {
    69         TRACE_ENTRY();
    70         fd_list_init(&all_handlers, NULL);
    71         fd_list_init(&any_handlers, NULL);
    72         /* if PTHREAD_RWLOCK_INITIALIZER is not supported on all platforms, we may initialize the lock here */
    73 }
    7466
    7567/* Call CBs from a given list (any_handlers if cb_list is NULL) -- must have locked fd_disp_lock before */
  • libfreeDiameter/fifo.c

    r11 r14  
    6565        void            (*l_cb)(struct fifo *, void **);
    6666        int             highest;/* The highest count value for which h_cb has been called */
     67        int             highest_ever; /* The max count value this queue has reached (for tweaking) */
    6768};
    6869
     
    118119        CHECK_POSIX_DO(  pthread_mutex_lock( &queue->mtx ), /* continue */  );
    119120        fd_log_debug("   %d elements in queue / %d threads waiting\n", queue->count, queue->thrs);
    120         fd_log_debug("   thresholds: %d / %d, cb: %p / %p (%p), highest: %d\n",
    121                         queue->high, queue->low,
     121        fd_log_debug("   thresholds: %d / %d (h:%d), cb: %p,%p (%p), highest: %d\n",
     122                        queue->high, queue->low, queue->highest,
    122123                        queue->h_cb, queue->l_cb, queue->data,
    123                         queue->highest);
     124                        queue->highest_ever);
    124125       
    125126        if (dump_item) {
     
    251252        fd_list_insert_before( &queue->list, new);
    252253        queue->count++;
     254        if (queue->highest_ever < queue->count)
     255                queue->highest_ever = queue->count;
    253256        if (queue->high && ((queue->count % queue->high) == 0)) {
    254257                call_cb = 1;
  • libfreeDiameter/init.c

    r7 r14  
    4949        /* Initialize the modules that need it */
    5050        fd_msg_eteid_init();
    51         fd_disp_init();
    5251        CHECK_FCT( fd_sess_init() );
    5352       
  • libfreeDiameter/libfD.h

    r7 r14  
    4545extern const char * type_base_name[];
    4646void fd_msg_eteid_init(void);
    47 void fd_disp_init(void);
    4847int fd_sess_init(void);
    4948
  • libfreeDiameter/lists.c

    r1 r14  
    4747
    4848#define CHECK_SINGLE( li ) {                    \
    49         ASSERT( FD_LIST(li)->next == (li) );    \
    50         ASSERT( FD_LIST(li)->prev == (li) );    \
    51         ASSERT( FD_LIST(li)->head == (li) );    \
     49        ASSERT( ((struct fd_list *)(li))->next == (li) );       \
     50        ASSERT( ((struct fd_list *)(li))->prev == (li) );       \
     51        ASSERT( ((struct fd_list *)(li))->head == (li) );       \
    5252}
    5353
  • libfreeDiameter/sessions.c

    r7 r14  
    117117
    118118/* Expiring sessions management */
    119 static struct fd_list   exp_sentinel;   /* list of sessions ordered by their timeout date */
     119static struct fd_list   exp_sentinel = FD_LIST_INITIALIZER(exp_sentinel);       /* list of sessions ordered by their timeout date */
    120120static pthread_mutex_t  exp_lock = PTHREAD_MUTEX_INITIALIZER;   /* lock protecting the list. */
    121121static pthread_cond_t   exp_cond = PTHREAD_COND_INITIALIZER;    /* condvar used by the expiry mecahinsm. */
     
    231231        }
    232232       
    233         /* Initialize expiry management */
    234         fd_list_init( &exp_sentinel, NULL );
     233        /* Start session garbage collector (expiry) */
    235234        CHECK_POSIX(  pthread_create(&exp_thr, NULL, exp_fct, NULL)  );
    236235       
     
    266265{
    267266        struct session_handler * del;
    268         struct fd_list deleted_states; /* Save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */
     267        /* place to save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */
     268        struct fd_list deleted_states = FD_LIST_INITIALIZER( deleted_states );
    269269        int i;
    270270       
     
    274274        del = *handler;
    275275        *handler = NULL;
    276         fd_list_init(&deleted_states, NULL);
    277276       
    278277        del->eyec = 0xdead; /* The handler is not valid anymore for any other operation */
     
    413412                fd_list_insert_after( li, &sess->expire );
    414413
     414                /* We added a new expiring element, we must signal */
     415                if (li == &exp_sentinel) {
     416                        CHECK_POSIX( pthread_cond_signal(&exp_cond) );
     417                }
     418               
    415419                #if 0
    416420                if (TRACE_BOOL(ANNOYING)) {     
     
    424428                #endif
    425429               
    426                 /* We added a new expiring element, we must signal */
    427                 CHECK_POSIX( pthread_cond_signal(&exp_cond) );
    428                
    429430                /* We're done */
    430431                CHECK_POSIX( pthread_mutex_unlock( &exp_lock ) );
     
    506507        fd_list_insert_before( li, &session->expire );
    507508
    508         /* We added a new expiring element, we must signal */
    509         CHECK_POSIX( pthread_cond_signal(&exp_cond) );
     509        /* We added a new expiring element, we must signal if it was in first position */
     510        if (session->expire.prev == &exp_sentinel) {
     511                CHECK_POSIX( pthread_cond_signal(&exp_cond) );
     512        }
    510513
    511514        #if 0
     
    588591}
    589592
    590 
    591 
    592593/* Save a state information with a session */
    593594int fd_sess_state_store_internal ( struct session_handler * handler, struct session * session, session_state ** state )
Note: See TracChangeset for help on using the changeset viewer.