Changeset 16:013ce9851131 in freeDiameter for freeDiameter/peers.c
- Timestamp:
- Oct 2, 2009, 6:57:06 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note: See TracChangeset
for help on using the changeset viewer.