Navigation


Changeset 13:ef9ef3bf4752 in freeDiameter for freeDiameter/peers.c


Ignore:
Timestamp:
Sep 30, 2009, 6:25:46 PM (15 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Progress on peer state machine

File:
1 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/peers.c

    r12 r13  
    5151pthread_rwlock_t fd_g_peers_rw;
    5252
    53 static int started = 0;
    54 static pthread_mutex_t  started_mtx = PTHREAD_MUTEX_INITIALIZER;
    55 static pthread_cond_t   started_cnd = PTHREAD_COND_INITIALIZER;
    56 
    57 /* Wait for start signal */
    58 int fd_peer_waitstart()
    59 {
    60         CHECK_POSIX( pthread_mutex_lock(&started_mtx) );
    61 awake: 
    62         if (! started) {
    63                 pthread_cleanup_push( fd_cleanup_mutex, &started_mtx );
    64                 CHECK_POSIX( pthread_cond_wait(&started_cnd, &started_mtx) );
    65                 pthread_cleanup_pop( 0 );
    66                 goto awake;
    67         }
    68         CHECK_POSIX( pthread_mutex_unlock(&started_mtx) );
    69         return 0;
    70 }
    71 
    72 /* Allow the state machines to start */
    73 int fd_peer_start()
    74 {
    75         CHECK_POSIX( pthread_mutex_lock(&started_mtx) );
    76         started = 1;
    77         CHECK_POSIX( pthread_cond_broadcast(&started_cnd) );
    78         CHECK_POSIX( pthread_mutex_unlock(&started_mtx) );
    79         return 0;
    80 }
    81 
    8253/* Initialize the peers list */
    8354int fd_peer_init()
     
    8758        fd_list_init(&fd_g_peers, NULL);
    8859        CHECK_POSIX( pthread_rwlock_init(&fd_g_peers_rw, NULL) );
     60       
     61        CHECK_FCT(fd_p_expi_init());
     62       
     63        return 0;
     64}
     65
     66/* Terminate peer module (destroy all peers) */
     67int fd_peer_fini()
     68{
     69        TRACE_ENTRY();
     70       
     71        CHECK_FCT_DO(fd_p_expi_fini(), /* continue */);
     72       
     73        TODO("Complete this function")
    8974       
    9075        return 0;
     
    119104}
    120105
     106/* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */
     107static int fd_sp_reinit(struct fd_peer ** ptr)
     108{
     109        struct fd_peer *p;
     110       
     111        TRACE_ENTRY("%p", ptr);
     112        CHECK_PARAMS(ptr);
     113       
     114        if (*ptr) {
     115                p = *ptr;
     116        } else {
     117                CHECK_MALLOC( p = malloc(sizeof(struct fd_peer)) );
     118                *ptr = p;
     119        }
     120       
     121        /* Now initialize the content */
     122        memset(p, 0, sizeof(struct fd_peer));
     123       
     124        fd_list_init(&p->p_hdr.chain, p);
     125       
     126        fd_list_init(&p->p_hdr.info.pi_endpoints, NULL);
     127        p->p_hdr.info.pi_state = STATE_DISABLED;
     128        fd_list_init(&p->p_hdr.info.pi_apps, NULL);
     129       
     130        p->p_eyec = EYEC_PEER;
     131        CHECK_POSIX( pthread_mutex_init(&p->p_mtx, NULL) );
     132        fd_list_init(&p->p_expiry, p);
     133        fd_list_init(&p->p_actives, p);
     134        p->p_hbh = lrand48();
     135        CHECK_FCT( fd_fifo_new(&p->p_events) );
     136        CHECK_FCT( fd_fifo_new(&p->p_recv) );
     137        CHECK_FCT( fd_fifo_new(&p->p_tosend) );
     138        fd_list_init(&p->p_sentreq, p);
     139       
     140        return 0;
     141}
     142
     143#define free_null( _v )         \
     144        if (_v) {               \
     145                free(_v);       \
     146                (_v) = NULL;    \
     147        }
     148       
     149#define free_list( _l )                                                 \
     150        while (!FD_IS_LIST_EMPTY(_l)) {                                 \
     151                struct fd_list * __li = ((struct fd_list *)(_l))->next; \
     152                fd_list_unlink(__li);                                   \
     153                free(__li);                                             \
     154        }
     155
     156/* Destroy a structure once all cleanups have been performed */
     157static int fd_sp_destroy(struct fd_peer ** ptr)
     158{
     159        struct fd_peer *p;
     160        void * t;
     161       
     162        TRACE_ENTRY("%p", ptr);
     163        CHECK_PARAMS(ptr);
     164        p = *ptr;
     165        *ptr = NULL;
     166        CHECK_PARAMS(p);
     167       
     168        CHECK_PARAMS( (p->p_refcount == 0) && FD_IS_LIST_EMPTY(&p->p_hdr.chain) );
     169       
     170        free_null(p->p_hdr.info.pi_diamid);
     171        free_null(p->p_hdr.info.pi_realm);
     172        free_list( &p->p_hdr.info.pi_endpoints );
     173        /* Assume the security data is already freed */
     174        free_null(p->p_hdr.info.pi_prodname);
     175        free_list( &p->p_hdr.info.pi_apps );
     176       
     177        free_null(p->p_dbgorig);
     178        CHECK_POSIX( pthread_mutex_destroy(&p->p_mtx) );
     179        ASSERT(FD_IS_LIST_EMPTY(&p->p_expiry));
     180        ASSERT(FD_IS_LIST_EMPTY(&p->p_actives));
     181       
     182        CHECK_FCT( fd_thr_term(&p->p_psm) );
     183        while ( fd_fifo_tryget(p->p_events, &t) == 0 ) {
     184                struct fd_event * ev = t;
     185                TRACE_DEBUG(FULL, "Found event %d(%p) in queue of peer %p being destroyed", ev->code, ev->data, p);
     186                free(ev);
     187        }
     188        CHECK_FCT( fd_fifo_del(&p->p_events) );
     189       
     190        CHECK_FCT( fd_thr_term(&p->p_inthr) );
     191        while ( fd_fifo_tryget(p->p_recv, &t) == 0 ) {
     192                struct msg * m = t;
     193                TRACE_DEBUG(FULL, "Found message %p in incoming queue of peer %p being destroyed", m, p);
     194                /* We simply destroy, the remote peer will re-send to someone else...*/
     195                CHECK_FCT(fd_msg_free(m));
     196        }
     197        CHECK_FCT( fd_fifo_del(&p->p_recv) );
     198       
     199        CHECK_FCT( fd_thr_term(&p->p_outthr) );
     200        while ( fd_fifo_tryget(p->p_tosend, &t) == 0 ) {
     201                struct msg * m = t;
     202                TRACE_DEBUG(FULL, "Found message %p in outgoing queue of peer %p being destroyed, requeue", m, p);
     203                /* We simply requeue in global, the routing thread will re-handle it. */
     204               
     205        }
     206        CHECK_FCT( fd_fifo_del(&p->p_tosend) );
     207       
     208        while (!FD_IS_LIST_EMPTY(&p->p_sentreq)) {
     209                struct sentreq * sr = (struct sentreq *)(p->p_sentreq.next);
     210                fd_list_unlink(&sr->chain);
     211                TRACE_DEBUG(FULL, "Found message %p in list of sent requests to peer %p being destroyed, requeue (fallback)", sr->req, p);
     212                CHECK_FCT(fd_fifo_post(fd_g_outgoing, &sr->req));
     213                free(sr);
     214        }
     215       
     216        TRACE_DEBUG(NONE, "TODO: destroy p->p_cnxctx here");
     217       
     218        if (p->p_cb)
     219                (*p->p_cb)(NULL, p->p_cb_data);
     220       
     221        free(p);
     222       
     223        return 0;
     224}
     225
     226/* Decrement refcount, delete if 0 */
     227int 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}
     254
    121255/* Add a new peer entry */
    122256int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data )
    123257{
    124         return ENOTSUP;
    125 }
     258        struct fd_peer *p = NULL;
     259        struct fd_list * li;
     260        int ret = 0;
     261        TRACE_ENTRY("%p %p %p %p", info, orig_dbg, cb, cb_data);
     262        CHECK_PARAMS(info && info->pi_diamid);
     263       
     264        /* Create a structure to contain the new peer information */
     265        CHECK_FCT( fd_sp_reinit(&p) );
     266       
     267        /* Copy the informations from the parameters received */
     268        CHECK_MALLOC( p->p_hdr.info.pi_diamid = strdup(info->pi_diamid) );
     269        if (info->pi_realm) {
     270                CHECK_MALLOC( p->p_hdr.info.pi_realm = strdup(info->pi_realm) );
     271        }
     272       
     273        p->p_hdr.info.pi_flags.pro3 = info->pi_flags.pro3;
     274        p->p_hdr.info.pi_flags.pro4 = info->pi_flags.pro4;
     275        p->p_hdr.info.pi_flags.alg  = info->pi_flags.alg;
     276        p->p_hdr.info.pi_flags.sec  = info->pi_flags.sec;
     277        p->p_hdr.info.pi_flags.exp  = info->pi_flags.exp;
     278       
     279        p->p_hdr.info.pi_lft     = info->pi_lft;
     280        p->p_hdr.info.pi_streams = info->pi_streams;
     281        p->p_hdr.info.pi_port    = info->pi_port;
     282        p->p_hdr.info.pi_tctimer = info->pi_tctimer;
     283        p->p_hdr.info.pi_twtimer = info->pi_twtimer;
     284       
     285        /* 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        }
     291       
     292        p->p_hdr.info.pi_sec_module = info->pi_sec_module;
     293        memcpy(&p->p_hdr.info.pi_sec_data, &info->pi_sec_data, sizeof(info->pi_sec_data));
     294       
     295        /* The internal data */
     296        if (orig_dbg) {
     297                CHECK_MALLOC( p->p_dbgorig = strdup(orig_dbg) );
     298        } else {
     299                CHECK_MALLOC( p->p_dbgorig = strdup("unknown") );
     300        }
     301        p->p_cb = cb;
     302        p->p_cb_data = cb_data;
     303       
     304        /* Ok, now check if we don't already have an entry with the same Diameter Id, and insert this one */
     305        CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) );
     306        CHECK_POSIX( pthread_mutex_lock( &p->p_mtx ) );
     307       
     308        for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     309                struct fd_peer * prev = (struct fd_peer *)li;
     310                int cmp = strcasecmp( p->p_hdr.info.pi_diamid, prev->p_hdr.info.pi_diamid );
     311                if (cmp < 0)
     312                        continue;
     313                if (cmp == 0)
     314                        ret = EEXIST;
     315                break;
     316        }
     317       
     318        /* We can insert the new peer object */
     319        if (! ret) {
     320                /* Update expiry list */
     321                CHECK_FCT_DO( ret = fd_p_expi_update( p, 1 ), goto out );
     322               
     323                /* Insert the new element in the list */
     324                fd_list_insert_before( li, &p->p_hdr.chain );
     325                p->p_refcount++;
     326        }
     327
     328out:   
     329        CHECK_POSIX( pthread_mutex_unlock( &p->p_mtx ) );
     330        CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
     331        if (ret) {
     332                CHECK_FCT( fd_sp_destroy(&p) );
     333        } else {
     334                CHECK_FCT( fd_psm_start(p) );
     335        }
     336        return ret;
     337}
Note: See TracChangeset for help on using the changeset viewer.