Mercurial > hg > freeDiameter
comparison freeDiameter/p_psm.c @ 34:0e2b57789361
Backup for the WE, some warnings remaining
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Fri, 30 Oct 2009 17:23:06 +0900 |
parents | e6fcdf12b9a0 |
children | 6486e97f56ae |
comparison
equal
deleted
inserted
replaced
33:e6fcdf12b9a0 | 34:0e2b57789361 |
---|---|
81 | 81 |
82 /************************************************************************/ | 82 /************************************************************************/ |
83 /* Manage the list of active peers */ | 83 /* Manage the list of active peers */ |
84 /************************************************************************/ | 84 /************************************************************************/ |
85 | 85 |
86 | |
87 /* Enter/leave OPEN state */ | 86 /* Enter/leave OPEN state */ |
88 static int enter_open_state(struct fd_peer * peer) | 87 static int enter_open_state(struct fd_peer * peer) |
89 { | 88 { |
89 struct fd_list * li; | |
90 CHECK_PARAMS( FD_IS_LIST_EMPTY(&peer->p_actives) ); | |
91 | |
92 /* Callback registered by the credential validator (fd_peer_validate_register) */ | |
93 if (peer->p_cb2) { | |
94 CHECK_FCT_DO( (*peer->p_cb2)(&peer->p_hdr.info), | |
95 { | |
96 TRACE_DEBUG(FULL, "Validation failed, moving to state CLOSING"); | |
97 peer->p_hdr.info.pi_state = STATE_CLOSING; | |
98 fd_psm_terminate(peer); | |
99 } ); | |
100 peer->p_cb2 = NULL; | |
101 return 0; | |
102 } | |
103 /* Insert in the active peers list */ | |
90 CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) ); | 104 CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) ); |
91 TODO(" insert in fd_g_activ_peers "); | 105 for (li = fd_g_activ_peers.next; li != &fd_g_activ_peers; li = li->next) { |
92 | 106 struct fd_peer * next_p = (struct fd_peer *)li->o; |
107 int cmp = strcmp(peer->p_hdr.info.pi_diamid, next_p->p_hdr.info.pi_diamid); | |
108 if (cmp < 0) | |
109 break; | |
110 } | |
111 fd_list_insert_before(li, &peer->p_actives); | |
93 CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) ); | 112 CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) ); |
113 | |
114 /* Callback registered when the peer was added, by fd_peer_add */ | |
115 if (peer->p_cb) { | |
116 TRACE_DEBUG(FULL, "Calling add callback for peer %s", peer->p_hdr.info.pi_diamid); | |
117 (*peer->p_cb)(&peer->p_hdr.info, peer->p_cb_data); | |
118 peer->p_cb = NULL; | |
119 peer->p_cb_data = NULL; | |
120 } | |
94 | 121 |
95 /* Start the thread to handle outgoing messages */ | 122 /* Start the thread to handle outgoing messages */ |
96 CHECK_FCT( fd_out_start(peer) ); | 123 CHECK_FCT( fd_out_start(peer) ); |
97 | 124 |
98 return ENOTSUP; | 125 return 0; |
99 } | 126 } |
100 static int leave_open_state(struct fd_peer * peer) | 127 static int leave_open_state(struct fd_peer * peer) |
101 { | 128 { |
102 TODO("Remove from active list"); | 129 /* Remove from active peers list */ |
130 CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) ); | |
131 fd_list_unlink( &peer->p_actives ); | |
132 CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) ); | |
103 | 133 |
104 /* Stop the "out" thread */ | 134 /* Stop the "out" thread */ |
105 CHECK_FCT( fd_out_stop(peer) ); | 135 CHECK_FCT( fd_out_stop(peer) ); |
106 | 136 |
107 TODO("Failover pending messages: requeue in global structures"); | 137 /* Failover the messages */ |
108 | 138 fd_peer_failover_msg(peer); |
109 return ENOTSUP; | 139 |
110 } | 140 return 0; |
141 } | |
142 | |
111 | 143 |
112 /************************************************************************/ | 144 /************************************************************************/ |
113 /* Helpers for state changes */ | 145 /* Helpers for state changes */ |
114 /************************************************************************/ | 146 /************************************************************************/ |
115 /* Change state */ | 147 /* Change state */ |
162 } | 194 } |
163 } | 195 } |
164 | 196 |
165 peer->p_psm_timer.tv_sec += delay; | 197 peer->p_psm_timer.tv_sec += delay; |
166 | 198 |
167 #if 0 | 199 #ifdef SLOW_PSM |
168 /* temporary for debug */ | 200 /* temporary for debug */ |
169 peer->p_psm_timer.tv_sec += 10; | 201 peer->p_psm_timer.tv_sec += 10; |
170 #endif | 202 #endif |
171 } | 203 } |
172 | 204 |
185 | 217 |
186 /* The state machine thread (controler) */ | 218 /* The state machine thread (controler) */ |
187 static void * p_psm_th( void * arg ) | 219 static void * p_psm_th( void * arg ) |
188 { | 220 { |
189 struct fd_peer * peer = (struct fd_peer *)arg; | 221 struct fd_peer * peer = (struct fd_peer *)arg; |
190 int created_started = started; | 222 int created_started = started ? 1 : 0; |
191 int event; | 223 int event; |
192 size_t ev_sz; | 224 size_t ev_sz; |
193 void * ev_data; | 225 void * ev_data; |
194 | 226 |
195 CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) ); | 227 CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) ); |
211 | 243 |
212 /* Initialize the timer */ | 244 /* Initialize the timer */ |
213 if (peer->p_flags.pf_responder) { | 245 if (peer->p_flags.pf_responder) { |
214 psm_next_timeout(peer, 0, INCNX_TIMEOUT); | 246 psm_next_timeout(peer, 0, INCNX_TIMEOUT); |
215 } else { | 247 } else { |
216 psm_next_timeout(peer, created_started ? 0 : 1, 0); | 248 psm_next_timeout(peer, created_started, 0); |
217 } | 249 } |
218 | 250 |
219 psm_loop: | 251 psm_loop: |
220 /* Get next event */ | 252 /* Get next event */ |
221 CHECK_FCT_DO( fd_event_timedget(peer->p_events, &peer->p_psm_timer, FDEVP_PSM_TIMEOUT, &event, &ev_sz, &ev_data), goto psm_end ); | 253 CHECK_FCT_DO( fd_event_timedget(peer->p_events, &peer->p_psm_timer, FDEVP_PSM_TIMEOUT, &event, &ev_sz, &ev_data), goto psm_end ); |
233 | 265 |
234 /* Purge invalid events */ | 266 /* Purge invalid events */ |
235 if (!CHECK_PEVENT(event)) { | 267 if (!CHECK_PEVENT(event)) { |
236 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); | 268 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); |
237 goto psm_loop; | 269 goto psm_loop; |
238 } | |
239 | |
240 /* Call the extension callback if needed */ | |
241 if (peer->p_cb) { | |
242 /* Check if we must call it */ | |
243 /* */ | |
244 /* OK */ | |
245 TODO("Call CB"); | |
246 TODO("Clear CB"); | |
247 } | 270 } |
248 | 271 |
249 /* Handle the (easy) debug event now */ | 272 /* Handle the (easy) debug event now */ |
250 if (event == FDEVP_DUMP_ALL) { | 273 if (event == FDEVP_DUMP_ALL) { |
251 fd_peer_dump(peer, ANNOYING); | 274 fd_peer_dump(peer, ANNOYING); |
274 } | 297 } |
275 } | 298 } |
276 | 299 |
277 /* A message was received */ | 300 /* A message was received */ |
278 if (event == FDEVP_CNX_MSG_RECV) { | 301 if (event == FDEVP_CNX_MSG_RECV) { |
279 TODO("Parse the buffer into a message"); | 302 struct msg * msg = NULL; |
280 /* parse_and_get_local_ccode */ | 303 struct msg_hdr * hdr; |
304 | |
305 /* Parse the received buffer */ | |
306 CHECK_FCT_DO( fd_msg_parse_buffer( (void *)&ev_data, ev_sz, &msg), | |
307 { | |
308 fd_log_debug("Received invalid data from peer '%s', closing the connection\n", peer->p_hdr.info.pi_diamid); | |
309 CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_end ); | |
310 goto psm_loop; | |
311 } ); | |
312 | |
313 TRACE_DEBUG(FULL, "Received this message from '%s':", peer->p_hdr.info.pi_diamid); | |
314 fd_msg_dump_walk(FULL, msg); | |
315 | |
316 /* Extract the header */ | |
317 CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end ); | |
318 | |
319 /* If it is an answer, associate with the request */ | |
320 if (!(hdr->msg_flags & CMD_FLAG_REQUEST)) { | |
321 struct msg * req; | |
322 /* Search matching request (same hbhid) */ | |
323 CHECK_FCT_DO( fd_p_sr_fetch(&peer->p_sr, hdr->msg_hbhid, &req), goto psm_end ); | |
324 if (req == NULL) { | |
325 fd_log_debug("Received a Diameter answer message with no corresponding sent request, discarding...\n"); | |
326 fd_msg_dump_walk(NONE, msg); | |
327 fd_msg_free(msg); | |
328 goto psm_loop; | |
329 } | |
330 | |
331 /* Associate */ | |
332 CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end ); | |
333 } | |
334 | |
335 /* We received a valid message, update the expiry timer */ | |
336 CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end ); | |
337 | |
338 /* Now handle non-link-local messages */ | |
339 if (fd_msg_is_routable(msg)) { | |
340 /* If we are not in OPEN state, discard the message */ | |
341 if (peer->p_hdr.info.pi_state != STATE_OPEN) { | |
342 fd_log_debug("Received a routable message while not in OPEN state from peer '%s', discarded.\n", peer->p_hdr.info.pi_diamid); | |
343 fd_msg_dump_walk(NONE, msg); | |
344 fd_msg_free(msg); | |
345 } else { | |
346 /* Set the message source and add the Route-Record */ | |
347 CHECK_FCT_DO( fd_msg_source_set( msg, peer->p_hdr.info.pi_diamid, 1, fd_g_config->cnf_dict ), goto psm_end); | |
348 | |
349 /* Requeue to the global incoming queue */ | |
350 CHECK_FCT_DO(fd_fifo_post(fd_g_incoming, &msg), goto psm_end ); | |
351 | |
352 /* Update the peer timer */ | |
353 if (!peer->p_flags.pf_dw_pending) { | |
354 psm_next_timeout(peer, 1, peer->p_hdr.info.pi_twtimer ?: fd_g_config->cnf_timer_tw); | |
355 } | |
356 } | |
357 goto psm_loop; | |
358 } | |
359 | |
360 /* Link-local message: They must be understood by our dictionary */ | |
361 | |
281 TODO("Check if it is a local message (CER, DWR, ...)"); | 362 TODO("Check if it is a local message (CER, DWR, ...)"); |
282 TODO("If not, check we are in OPEN state"); | 363 TODO("If not, check we are in OPEN state"); |
283 TODO("Update expiry timer if needed"); | 364 TODO("Update expiry timer if needed"); |
284 TODO("Handle the message"); | 365 TODO("Handle the message"); |
285 } | 366 } |
316 ASSERT(params); | 397 ASSERT(params); |
317 | 398 |
318 switch (peer->p_hdr.info.pi_state) { | 399 switch (peer->p_hdr.info.pi_state) { |
319 case STATE_CLOSED: | 400 case STATE_CLOSED: |
320 TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state"); | 401 TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state"); |
402 /* In case of error : DIAMETER_UNKNOWN_PEER */ | |
321 break; | 403 break; |
322 | 404 |
323 case STATE_WAITCNXACK: | 405 case STATE_WAITCNXACK: |
324 case STATE_WAITCEA: | 406 case STATE_WAITCEA: |
325 TODO("Election"); | 407 TODO("Election"); |
350 /* We have not handled timeout in this state, let's postpone next alert */ | 432 /* We have not handled timeout in this state, let's postpone next alert */ |
351 psm_next_timeout(peer, 0, 60); | 433 psm_next_timeout(peer, 0, 60); |
352 } | 434 } |
353 | 435 |
354 goto psm_loop; | 436 goto psm_loop; |
355 | 437 |
356 psm_end: | 438 psm_end: |
357 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ | 439 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ |
358 peer->p_psm = (pthread_t)NULL; | 440 peer->p_psm = (pthread_t)NULL; |
359 pthread_detach(pthread_self()); | 441 pthread_detach(pthread_self()); |
360 return NULL; | 442 return NULL; |
395 | 477 |
396 /* End the PSM & cleanup the peer structure */ | 478 /* End the PSM & cleanup the peer structure */ |
397 void fd_psm_abord(struct fd_peer * peer ) | 479 void fd_psm_abord(struct fd_peer * peer ) |
398 { | 480 { |
399 TRACE_ENTRY("%p", peer); | 481 TRACE_ENTRY("%p", peer); |
400 TODO("Cancel PSM thread"); | 482 |
401 TODO("Cancel OUT thread"); | 483 /* Cancel PSM thread */ |
402 TODO("Cleanup the peer connection object"); | 484 CHECK_FCT_DO( fd_thr_term(&peer->p_psm), /* continue */ ); |
403 TODO("Cleanup the message queues (requeue)"); | 485 |
404 TODO("Call p_cb with NULL parameter if needed"); | 486 /* Cancel the OUT thread */ |
405 | 487 CHECK_FCT_DO( fd_out_stop(peer), /* continue */ ); |
488 | |
489 /* Cleanup the connection */ | |
490 if (peer->p_cnxctx) { | |
491 fd_cnx_destroy(peer->p_cnxctx); | |
492 } | |
493 | |
494 /* Failover the messages */ | |
495 fd_peer_failover_msg(peer); | |
496 | |
497 /* Empty the events list, this might leak some memory, but we only do it on exit, so... */ | |
498 fd_event_destroy(&peer->p_events, free); | |
499 | |
500 /* More cleanups are performed in fd_peer_free */ | |
406 return; | 501 return; |
407 } | 502 } |
408 | 503 |