Changeset 16:013ce9851131 in freeDiameter
- Timestamp:
- Oct 2, 2009, 6:57:06 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/CMakeLists.txt
r13 r16 27 27 ) 28 28 29 # Require GNU TLS for building the daemon 30 FIND_PACKAGE(GNUTLS REQUIRED) 31 INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIRS}) 32 SET(FD_LIBS ${FD_LIBS} ${GNUTLS_LIBRARIES}) 29 33 30 34 # Building the executable -
freeDiameter/fD.h
r14 r16 151 151 /* Events codespace for struct fd_peer->p_events */ 152 152 enum { 153 /* Dump all info about this peer in the debug log */ 154 FDEVP_DUMP_ALL = 2000 155 153 156 /* request to terminate this peer : disconnect, requeue all messages */ 154 FDEVP_TERMINATE = 2000 155 156 /* Dump all info about this peer in the debug log */ 157 ,FDEVP_DUMP_ALL 157 ,FDEVP_TERMINATE 158 158 159 159 /* A message was received in the peer */ … … 164 164 }; 165 165 const char * fd_pev_str(int event); 166 #define CHECK_EVENT( _e ) \ 167 (((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT)) 166 168 167 169 /* Structure to store a sent request */ … … 174 176 int fd_peer_fini(); 175 177 void fd_peer_dump_list(int details); 178 void fd_peer_dump(struct fd_peer * peer, int details); 179 int fd_peer_alloc(struct fd_peer ** ptr); 180 int fd_peer_free(struct fd_peer ** ptr); 176 181 /* fd_peer_add declared in freeDiameter.h */ 177 182 -
freeDiameter/main.c
r14 r16 38 38 #include <signal.h> 39 39 #include <getopt.h> 40 #include <locale.h> 41 42 #ifdef GCRY_THREAD_OPTION_PTHREAD_IMPL 43 GCRY_THREAD_OPTION_PTHREAD_IMPL; 44 #endif /* GCRY_THREAD_OPTION_PTHREAD_IMPL */ 45 40 46 41 47 /* forward declarations */ … … 62 68 /* Initialize the library */ 63 69 CHECK_FCT( fd_lib_init() ); 70 TRACE_DEBUG(INFO, "libfreeDiameter initialized."); 64 71 65 72 /* Name this thread */ … … 71 78 /* Parse the command-line */ 72 79 CHECK_FCT( main_cmdline(argc, argv) ); 80 81 /* Initialize gnutls */ 82 CHECK_GNUTLS_DO( gnutls_global_init(), return EINVAL ); 83 if ( ! gnutls_check_version(GNUTLS_VERSION) ) { 84 fprintf(stderr, "The GNUTLS library is too old; found '%s', need '" GNUTLS_VERSION "'\n", gnutls_check_version(NULL)); 85 return EINVAL; 86 } else { 87 TRACE_DEBUG(INFO, "GNUTLS library '%s' initialized.", gnutls_check_version(NULL)); 88 } 73 89 74 90 /* Allow SIGINT and SIGTERM from this point */ … … 141 157 142 158 CHECK_FCT_DO( fd_thr_term(&sig_th), /* continue */ ); 159 160 gnutls_global_deinit(); 143 161 144 162 return ret; … … 168 186 int c; 169 187 int option_index = 0; 188 char * locale; 170 189 171 190 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 } 191 { "help", no_argument, NULL, 'h' }, 192 { "version", no_argument, NULL, 'V' }, 193 { "config", required_argument, NULL, 'c' }, 194 { "debug", no_argument, NULL, 'd' }, 195 { "quiet", no_argument, NULL, 'q' }, 196 { "dbglocale", optional_argument, NULL, 'l' }, 197 { NULL, 0, NULL, 0 } 178 198 }; 179 199 … … 182 202 /* Loop on arguments */ 183 203 while (1) { 184 c = getopt_long (argc, argv, "hVc:dq ", long_options, &option_index);204 c = getopt_long (argc, argv, "hVc:dql:", long_options, &option_index); 185 205 if (c == -1) 186 206 break; /* Exit from the loop. */ … … 200 220 break; 201 221 222 case 'l': /* Change the locale. */ 223 locale = setlocale(LC_ALL, optarg?:""); 224 if (locale) { 225 TRACE_DEBUG(INFO, "Locale set to: %s", optarg ?: locale); 226 } else { 227 TRACE_DEBUG(INFO, "Unable to set locale (%s)", optarg); 228 return EINVAL; 229 } 230 break; 231 202 232 case 'd': /* Increase verbosity of debug messages. */ 203 233 fd_g_debug_lvl++; … … 210 240 case '?': /* Invalid option. */ 211 241 /* `getopt_long' already printed an error message. */ 212 TRACE_DEBUG(INFO, "getopt_long found an invalid character \n");242 TRACE_DEBUG(INFO, "getopt_long found an invalid character"); 213 243 return EINVAL; 214 244 215 245 default: /* bug: option not considered. */ 216 TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c \n", c);246 TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c", c); 217 247 ASSERT(0); 218 248 return EINVAL; … … 267 297 printf( "\nDebug:\n" 268 298 " These options are mostly useful for developers\n" 299 " -l, --dbglocale Set the locale for error messages\n" 269 300 " -d, --debug Increase verbosity of debug messages\n" 270 301 " -q, --quiet Decrease verbosity then remove debug messages\n"); -
freeDiameter/p_expiry.c
r14 r16 36 36 #include "fD.h" 37 37 38 /* Delay for garbage collection of expired threads, in seconds */ 39 #define GC_TIME 60 40 38 41 static pthread_t exp_thr; 42 static pthread_t gc_thr; 39 43 static struct fd_list exp_list = FD_LIST_INITIALIZER( exp_list ); 40 44 static pthread_cond_t exp_cnd = PTHREAD_COND_INITIALIZER; 41 45 static pthread_mutex_t exp_mtx = PTHREAD_MUTEX_INITIALIZER; 46 47 static void * gc_th_fct(void * arg) 48 { 49 fd_log_threadname ( "Peers/garbage" ); 50 TRACE_ENTRY( "" ); 51 52 do { 53 struct fd_list * li, purge = FD_LIST_INITIALIZER(purge); 54 55 pthread_testcancel(); 56 sleep(GC_TIME); 57 58 /* Now check in the peers list if any peer can be deleted */ 59 CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), goto error ); 60 61 for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { 62 struct fd_peer * peer = (struct fd_peer *)li; 63 64 if (peer->p_hdr.info.pi_state != STATE_ZOMBIE) 65 continue; 66 67 if (peer->p_hdr.info.pi_flags.exp == PI_EXP_NONE) 68 continue; /* This peer was not supposed to expire, keep it in the list */ 69 70 /* Ok, the peer was expired, let's remove it */ 71 li = li->prev; /* to avoid breaking the loop */ 72 fd_list_unlink(&peer->p_hdr.chain); 73 fd_list_insert_before(&purge, &peer->p_hdr.chain); 74 } 75 76 CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), goto error ); 77 78 /* Now delete peers that are in the purge list */ 79 while (!FD_IS_LIST_EMPTY(&purge)) { 80 struct fd_peer * peer = (struct fd_peer *)(purge.next); 81 fd_list_unlink(&peer->p_hdr.chain); 82 TRACE_DEBUG(INFO, "Garbage Collect: delete zombie peer '%s'", peer->p_hdr.info.pi_diamid); 83 CHECK_FCT_DO( fd_peer_free(&peer), /* Continue... what else to do ? */ ); 84 } 85 } while (1); 86 87 error: 88 TRACE_DEBUG(INFO, "An error occurred in peers module! GC thread is terminating..."); 89 ASSERT(0); 90 CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), ); 91 return NULL; 92 } 93 42 94 43 95 static void * exp_th_fct(void * arg) … … 98 150 TRACE_ENTRY(); 99 151 CHECK_FCT( pthread_create( &exp_thr, NULL, exp_th_fct, NULL ) ); 152 CHECK_FCT( pthread_create( &gc_thr, NULL, gc_th_fct, NULL ) ); 100 153 return 0; 101 154 } … … 113 166 114 167 CHECK_POSIX( pthread_mutex_unlock(&exp_mtx) ); 168 CHECK_FCT_DO( fd_thr_term(&gc_thr), ); 115 169 return 0; 116 170 } -
freeDiameter/p_psm.c
r14 r16 37 37 38 38 const char *peer_state_str[] = { 39 "STATE_ ZOMBIE"39 "STATE_NEW" 40 40 , "STATE_OPEN" 41 41 , "STATE_CLOSED" … … 46 46 , "STATE_SUSPECT" 47 47 , "STATE_REOPEN" 48 , "STATE_ZOMBIE" 48 49 }; 49 50 … … 123 124 } 124 125 126 /* Wait for the next event in the PSM, or timeout */ 125 127 static int psm_ev_timedget(struct fd_peer * peer, int *code, void ** data) 126 128 { … … 142 144 143 145 return 0; 144 } 145 146 /* The state machine thread */146 } 147 148 /* The state machine thread (controler) */ 147 149 static void * p_psm_th( void * arg ) 148 150 { 149 151 struct fd_peer * peer = (struct fd_peer *)arg; 150 152 int created_started = started; 153 int event; 154 void * ev_data; 151 155 152 156 CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) ); … … 161 165 } 162 166 163 /* Wait that the PSM are authorized to start in the daemon */164 CHECK_FCT_DO( fd_psm_waitstart(), goto end );165 166 167 /* The state machine starts in CLOSED state */ 167 168 peer->p_hdr.info.pi_state = STATE_CLOSED; 169 170 /* Wait that the PSM are authorized to start in the daemon */ 171 CHECK_FCT_DO( fd_psm_waitstart(), goto psm_end ); 168 172 169 173 /* Initialize the timer */ … … 174 178 } 175 179 176 psm: 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 194 end: 195 /* set STATE_ZOMBIE */ 196 pthread_cleanup_pop(1); 180 psm_loop: 181 /* Get next event */ 182 CHECK_FCT_DO( psm_ev_timedget(peer, &event, &ev_data), goto psm_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 /* The following two states are impossible */ 191 ASSERT( peer->p_hdr.info.pi_state != STATE_NEW ); 192 ASSERT( peer->p_hdr.info.pi_state != STATE_ZOMBIE ); 193 194 /* Purge invalid events */ 195 if (!CHECK_EVENT(event)) { 196 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); 197 goto psm_loop; 198 } 199 200 /* Handle the (easy) debug event now */ 201 if (event == FDEVP_DUMP_ALL) { 202 fd_peer_dump(peer, ANNOYING); 203 goto psm_loop; 204 } 205 206 /* Requests to terminate the peer object */ 207 if (event == FDEVP_TERMINATE) { 208 switch (peer->p_hdr.info.pi_state) { 209 case STATE_CLOSING: 210 case STATE_WAITCNXACK: 211 case STATE_WAITCNXACK_ELEC: 212 case STATE_WAITCEA: 213 case STATE_SUSPECT: 214 /* In these cases, we just cleanup the peer object and terminate now */ 215 TODO("Cleanup the PSM: terminate connection object, ..."); 216 case STATE_CLOSED: 217 /* Then we just terminate the PSM */ 218 goto psm_end; 219 220 case STATE_OPEN: 221 case STATE_REOPEN: 222 /* We cannot just close the conenction, we have to send a DPR first */ 223 TODO("Send DPR, mark the peer as CLOSING"); 224 goto psm_loop; 225 } 226 } 227 228 /* MSG_RECEIVED: fd_p_expi_update(struct fd_peer * peer ) */ 229 /* If timeout or OPEN : call cb if defined */ 230 231 /* Default action : the handling has not yet been implemented. */ 232 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event)); 233 if (event == FDEVP_PSM_TIMEOUT) { 234 /* We have not handled timeout in this state, let's postpone next alert */ 235 psm_next_timeout(peer, 0, 60); 236 } 237 238 goto psm_loop; 239 240 psm_end: 241 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ 197 242 return NULL; 198 243 } … … 205 250 { 206 251 TRACE_ENTRY("%p", peer); 207 TODO(""); 208 return ENOTSUP; 252 253 /* Check the peer and state are OK */ 254 CHECK_PARAMS( CHECK_PEER(peer) && (peer->p_hdr.info.pi_state == STATE_NEW) ); 255 256 /* Create the PSM controler thread */ 257 CHECK_POSIX( pthread_create( &peer->p_psm, NULL, p_psm_th, peer ) ); 258 259 /* We're done */ 260 return 0; 209 261 } 210 262 … … 214 266 TRACE_ENTRY("%p", peer); 215 267 CHECK_PARAMS( CHECK_PEER(peer) ); 216 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, NULL) ); 268 if (peer->p_hdr.info.pi_state != STATE_ZOMBIE) { 269 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, NULL) ); 270 } else { 271 TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid); 272 } 217 273 return 0; 218 274 } … … 225 281 TODO("Cancel IN thread"); 226 282 TODO("Cancel OUT thread"); 227 TODO("Cleanup the connection"); 283 TODO("Cleanup the peer connection object"); 284 TODO("Cleanup the message queues (requeue)"); 228 285 return; 229 286 } -
freeDiameter/peers.c
r14 r16 36 36 #include "fD.h" 37 37 38 /* Global list of peers */ 38 39 struct fd_list fd_g_peers = FD_LIST_INITIALIZER(fd_g_peers); 39 40 pthread_rwlock_t fd_g_peers_rw = PTHREAD_RWLOCK_INITIALIZER; 40 41 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 }92 42 93 43 /* 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)44 int fd_peer_alloc(struct fd_peer ** ptr) 95 45 { 96 46 struct fd_peer *p; … … 126 76 } 127 77 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 213 78 /* Add a new peer entry */ 214 79 int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data ) … … 221 86 222 87 /* Create a structure to contain the new peer information */ 223 CHECK_FCT( fd_ sp_reinit(&p) );88 CHECK_FCT( fd_peer_alloc(&p) ); 224 89 225 90 /* Copy the informations from the parameters received */ … … 248 113 fd_list_insert_before(&p->p_hdr.info.pi_endpoints, li); 249 114 } 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));253 115 254 116 /* The internal data */ … … 286 148 CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); 287 149 if (ret) { 288 CHECK_FCT( fd_ sp_destroy(&p) );150 CHECK_FCT( fd_peer_free(&p) ); 289 151 } else { 290 152 CHECK_FCT( fd_psm_begin(p) ); … … 292 154 return ret; 293 155 } 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 */ 172 int 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) */ 243 int 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 */ 320 void 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 */ 357 void 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 -
include/freeDiameter/freeDiameter.h
r14 r16 39 39 40 40 #include <freeDiameter/libfreeDiameter.h> 41 #include <gnutls/gnutls.h> 42 #include <gnutls/x509.h> 43 44 /* GNUTLS version */ 45 #ifndef GNUTLS_VERSION 46 #define GNUTLS_VERSION LIBGNUTLS_VERSION 47 #endif /* GNUTLS_VERSION */ 48 49 /* Check the return value of a GNUTLS function, log and propagate */ 50 #define CHECK_GNUTLS_DO( __call__, __fallback__ ) { \ 51 int __ret__; \ 52 TRACE_DEBUG_ALL( "Check FCT: " #__call__ ); \ 53 __ret__ = (__call__); \ 54 if (__ret__ < 0) { \ 55 TRACE_DEBUG(INFO, "Error in '" #__call__ "':\t%s", gnutls_strerror(__ret__)); \ 56 __fallback__; \ 57 } \ 58 } 41 59 42 60 … … 70 88 unsigned tls_alg: 1; /* TLS algorithm for initiated cnx. 0: separate port. 1: inband-security (old) */ 71 89 } cnf_flags; 90 91 struct { 92 /* GNUTLS global state */ 93 /* Server credential(s) */ 94 } cnf_sec_data; 72 95 73 96 uint32_t cnf_orstateid; /* The value to use in Origin-State-Id, default to random value */ … … 151 174 enum peer_state { 152 175 /* Stable states */ 153 STATE_ ZOMBIE = 0, /* The threads handling the peer are not running for some reason*/176 STATE_NEW = 0, /* The peer has been just been created, PSM thread not started yet */ 154 177 STATE_OPEN, /* Connexion established */ 155 178 … … 168 191 STATE_SUSPECT, /* A DWR was sent and not answered within TwTime. Failover in progress. */ 169 192 STATE_REOPEN, /* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */ 193 194 /* Error state */ 195 STATE_ZOMBIE /* The PSM thread is not running anymore; it must be re-started or peer should be deleted. */ 196 #define STATE_MAX STATE_ZOMBIE 170 197 }; 171 198 extern const char *peer_state_str[]; 172 199 #define STATE_STR(state) \ 173 (((unsigned)(state)) <= STATE_ REOPEN? peer_state_str[((unsigned)(state)) ] : "<Invalid>")200 (((unsigned)(state)) <= STATE_MAX ? peer_state_str[((unsigned)(state)) ] : "<Invalid>") 174 201 175 202 /* Information about a remote peer. Same structure is used for creating a new entry, but not all fields are meaningful in that case */ … … 220 247 221 248 struct fd_list pi_endpoints; /* Endpoint(s) of the remote peer (configured, discovered, or advertized). list of struct fd_endpoint. DNS resolved if empty. */ 222 223 /* TLS specific data -- the exact data pointed here depends on the security module in use (ex: gnutls, ...) */224 enum {225 PI_SEC_GNUTLS = 0, /* The security module is GNUTLS, this is the default */226 PI_SEC_OTHER /* Another security module (TBD) */227 } pi_sec_module;228 union {229 /* Security data when pi_sec_module == PI_SEC_GNUTLS */230 struct {231 void * CA; /* Authority to use to validate this peer credentials (a CA or root certificate) -- use default if NULL */232 void * cred; /* The (valid) credentials that the peer has presented */233 } gnutls;234 /* Security data when pi_sec_module == PI_SEC_OTHER */235 struct {236 void * dummy; /* Something meaningful for the other security module */237 } other;238 } pi_sec_data;239 249 240 250 /* The remaining information must not be modified, and is not used for peer creation */ … … 245 255 uint32_t pi_firmrev; /* Content of the Firmware-Revision AVP */ 246 256 struct fd_list pi_apps; /* applications advertised by the remote peer, except relay (pi_flags.relay) */ 257 struct { 258 /* This is inspired from http://www.gnu.org/software/gnutls/manual/gnutls.html#ex_003ax509_002dinfo */ 259 const gnutls_datum_t *cert_list; /* The (valid) credentials that the peer has presented */ 260 unsigned int cert_list_size;/* Number of certificates in the list */ 261 } pi_sec_data; 247 262 }; 248 263
Note: See TracChangeset
for help on using the changeset viewer.