Changeset 13:ef9ef3bf4752 in freeDiameter for freeDiameter/peers.c
- Timestamp:
- Sep 30, 2009, 6:25:46 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/peers.c
r12 r13 51 51 pthread_rwlock_t fd_g_peers_rw; 52 52 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 82 53 /* Initialize the peers list */ 83 54 int fd_peer_init() … … 87 58 fd_list_init(&fd_g_peers, NULL); 88 59 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) */ 67 int fd_peer_fini() 68 { 69 TRACE_ENTRY(); 70 71 CHECK_FCT_DO(fd_p_expi_fini(), /* continue */); 72 73 TODO("Complete this function") 89 74 90 75 return 0; … … 119 104 } 120 105 106 /* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */ 107 static 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 */ 157 static 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 */ 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 } 254 121 255 /* Add a new peer entry */ 122 256 int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data ) 123 257 { 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 328 out: 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.