Mercurial > hg > freeDiameter
comparison freeDiameter/p_psm.c @ 37:cc3c59fe98fe
Lot of cleanups in peer structure management
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 05 Nov 2009 14:28:46 +0900 |
parents | 1498b3c7304c |
children | 68c1890f7049 |
comparison
equal
deleted
inserted
replaced
36:1498b3c7304c | 37:cc3c59fe98fe |
---|---|
92 /* Callback registered by the credential validator (fd_peer_validate_register) */ | 92 /* Callback registered by the credential validator (fd_peer_validate_register) */ |
93 if (peer->p_cb2) { | 93 if (peer->p_cb2) { |
94 CHECK_FCT_DO( (*peer->p_cb2)(&peer->p_hdr.info), | 94 CHECK_FCT_DO( (*peer->p_cb2)(&peer->p_hdr.info), |
95 { | 95 { |
96 TRACE_DEBUG(FULL, "Validation failed, moving to state CLOSING"); | 96 TRACE_DEBUG(FULL, "Validation failed, moving to state CLOSING"); |
97 peer->p_hdr.info.pi_state = STATE_CLOSING; | 97 peer->p_hdr.info.runtime.pir_state = STATE_CLOSING; |
98 fd_psm_terminate(peer); | 98 fd_psm_terminate(peer); |
99 } ); | 99 } ); |
100 peer->p_cb2 = NULL; | 100 peer->p_cb2 = NULL; |
101 return 0; | 101 return 0; |
102 } | 102 } |
120 } | 120 } |
121 | 121 |
122 /* Start the thread to handle outgoing messages */ | 122 /* Start the thread to handle outgoing messages */ |
123 CHECK_FCT( fd_out_start(peer) ); | 123 CHECK_FCT( fd_out_start(peer) ); |
124 | 124 |
125 /* Update the expiry timer now */ | |
126 CHECK_FCT( fd_p_expi_update(peer) ); | |
127 | |
125 return 0; | 128 return 0; |
126 } | 129 } |
127 static int leave_open_state(struct fd_peer * peer) | 130 static int leave_open_state(struct fd_peer * peer) |
128 { | 131 { |
129 /* Remove from active peers list */ | 132 /* Remove from active peers list */ |
142 | 145 |
143 | 146 |
144 /************************************************************************/ | 147 /************************************************************************/ |
145 /* Helpers for state changes */ | 148 /* Helpers for state changes */ |
146 /************************************************************************/ | 149 /************************************************************************/ |
150 | |
151 /* Cleanup pending events in the peer */ | |
152 void fd_psm_events_free(struct fd_peer * peer) | |
153 { | |
154 struct fd_event * ev; | |
155 /* Purge all events, and free the associated data if any */ | |
156 while (fd_fifo_tryget( peer->p_events, &ev ) == 0) { | |
157 switch (ev->code) { | |
158 case FDEVP_CNX_ESTABLISHED: { | |
159 fd_cnx_destroy(ev->data); | |
160 } | |
161 break; | |
162 | |
163 case FDEVP_CNX_INCOMING: { | |
164 struct cnx_incoming * evd = ev->data; | |
165 CHECK_FCT_DO( fd_msg_free(evd->cer), /* continue */); | |
166 fd_cnx_destroy(evd->cnx); | |
167 } | |
168 default: | |
169 free(ev->data); | |
170 } | |
171 free(ev); | |
172 } | |
173 } | |
174 | |
175 | |
147 /* Change state */ | 176 /* Change state */ |
148 int fd_psm_change_state(struct fd_peer * peer, int new_state) | 177 int fd_psm_change_state(struct fd_peer * peer, int new_state) |
149 { | 178 { |
150 int old; | 179 int old; |
151 | 180 |
152 TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state)); | 181 TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state)); |
153 CHECK_PARAMS( CHECK_PEER(peer) ); | 182 CHECK_PARAMS( CHECK_PEER(peer) ); |
154 old = peer->p_hdr.info.pi_state; | 183 old = peer->p_hdr.info.runtime.pir_state; |
155 if (old == new_state) | 184 if (old == new_state) |
156 return 0; | 185 return 0; |
157 | 186 |
158 TRACE_DEBUG(FULL, "'%s'\t-> '%s'\t'%s'", | 187 TRACE_DEBUG(FULL, "'%s'\t-> '%s'\t'%s'", |
159 STATE_STR(old), | 188 STATE_STR(old), |
162 | 191 |
163 if (old == STATE_OPEN) { | 192 if (old == STATE_OPEN) { |
164 CHECK_FCT( leave_open_state(peer) ); | 193 CHECK_FCT( leave_open_state(peer) ); |
165 } | 194 } |
166 | 195 |
167 peer->p_hdr.info.pi_state = new_state; | 196 peer->p_hdr.info.runtime.pir_state = new_state; |
168 | 197 |
169 if (new_state == STATE_OPEN) { | 198 if (new_state == STATE_OPEN) { |
170 CHECK_FCT( enter_open_state(peer) ); | 199 CHECK_FCT( enter_open_state(peer) ); |
171 } | 200 } |
172 | 201 |
173 if ((new_state == STATE_CLOSED) && (peer->p_hdr.info.pi_flags.persist == PI_PRST_NONE)) { | 202 if (new_state == STATE_CLOSED) { |
174 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) ); | 203 /* Purge event list */ |
204 fd_psm_events_free(peer); | |
205 | |
206 /* If the peer is not persistant, we destroy it */ | |
207 if (peer->p_hdr.info.config.pic_flags.persist == PI_PRST_NONE) { | |
208 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) ); | |
209 } | |
175 } | 210 } |
176 | 211 |
177 return 0; | 212 return 0; |
178 } | 213 } |
179 | 214 |
207 } | 242 } |
208 | 243 |
209 /* Cleanup the peer */ | 244 /* Cleanup the peer */ |
210 void fd_psm_cleanup(struct fd_peer * peer) | 245 void fd_psm_cleanup(struct fd_peer * peer) |
211 { | 246 { |
212 /* Move to CLOSED state */ | 247 /* Move to CLOSED state: failover messages, stop OUT thread, unlink peer from active list */ |
213 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ ); | 248 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ ); |
214 | 249 |
215 /* Destroy the connection */ | 250 /* Destroy data */ |
251 CHECK_FCT_DO( fd_thr_term(&peer->p_ini_thr), /* continue */); | |
216 if (peer->p_cnxctx) { | 252 if (peer->p_cnxctx) { |
217 fd_cnx_destroy(peer->p_cnxctx); | 253 fd_cnx_destroy(peer->p_cnxctx); |
218 peer->p_cnxctx = NULL; | 254 peer->p_cnxctx = NULL; |
219 } | 255 } |
220 | 256 if (peer->p_initiator) { |
221 /* What else ? */ | 257 fd_cnx_destroy(peer->p_initiator); |
222 TODO("..."); | 258 peer->p_initiator = NULL; |
259 } | |
260 if (peer->p_receiver) { | |
261 fd_cnx_destroy(peer->p_receiver); | |
262 peer->p_receiver = NULL; | |
263 } | |
223 | 264 |
224 } | 265 } |
225 | 266 |
226 | 267 |
227 /************************************************************************/ | 268 /************************************************************************/ |
230 /* Cancelation cleanup : set ZOMBIE state in the peer */ | 271 /* Cancelation cleanup : set ZOMBIE state in the peer */ |
231 void cleanup_setstate(void * arg) | 272 void cleanup_setstate(void * arg) |
232 { | 273 { |
233 struct fd_peer * peer = (struct fd_peer *)arg; | 274 struct fd_peer * peer = (struct fd_peer *)arg; |
234 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); | 275 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); |
235 peer->p_hdr.info.pi_state = STATE_ZOMBIE; | 276 peer->p_hdr.info.runtime.pir_state = STATE_ZOMBIE; |
236 return; | 277 return; |
237 } | 278 } |
238 | 279 |
239 /* The state machine thread (controler) */ | 280 /* The state machine thread (controler) */ |
240 static void * p_psm_th( void * arg ) | 281 static void * p_psm_th( void * arg ) |
255 sprintf(buf, "PSM/%.*s", sizeof(buf) - 5, peer->p_hdr.info.pi_diamid); | 296 sprintf(buf, "PSM/%.*s", sizeof(buf) - 5, peer->p_hdr.info.pi_diamid); |
256 fd_log_threadname ( buf ); | 297 fd_log_threadname ( buf ); |
257 } | 298 } |
258 | 299 |
259 /* The state machine starts in CLOSED state */ | 300 /* The state machine starts in CLOSED state */ |
260 peer->p_hdr.info.pi_state = STATE_CLOSED; | 301 peer->p_hdr.info.runtime.pir_state = STATE_CLOSED; |
261 | 302 |
262 /* Wait that the PSM are authorized to start in the daemon */ | 303 /* Wait that the PSM are authorized to start in the daemon */ |
263 CHECK_FCT_DO( fd_psm_waitstart(), goto psm_end ); | 304 CHECK_FCT_DO( fd_psm_waitstart(), goto psm_end ); |
264 | 305 |
265 /* Initialize the timer */ | 306 /* Initialize the timer */ |
271 | 312 |
272 psm_loop: | 313 psm_loop: |
273 /* Get next event */ | 314 /* Get next event */ |
274 CHECK_FCT_DO( fd_event_timedget(peer->p_events, &peer->p_psm_timer, FDEVP_PSM_TIMEOUT, &event, &ev_sz, &ev_data), goto psm_end ); | 315 CHECK_FCT_DO( fd_event_timedget(peer->p_events, &peer->p_psm_timer, FDEVP_PSM_TIMEOUT, &event, &ev_sz, &ev_data), goto psm_end ); |
275 TRACE_DEBUG(FULL, "'%s'\t<-- '%s'\t(%p,%zd)\t'%s'", | 316 TRACE_DEBUG(FULL, "'%s'\t<-- '%s'\t(%p,%zd)\t'%s'", |
276 STATE_STR(peer->p_hdr.info.pi_state), | 317 STATE_STR(peer->p_hdr.info.runtime.pir_state), |
277 fd_pev_str(event), ev_data, ev_sz, | 318 fd_pev_str(event), ev_data, ev_sz, |
278 peer->p_hdr.info.pi_diamid); | 319 peer->p_hdr.info.pi_diamid); |
279 | 320 |
280 /* Now, the action depends on the current state and the incoming event */ | 321 /* Now, the action depends on the current state and the incoming event */ |
281 | 322 |
282 /* The following states are impossible */ | 323 /* The following states are impossible */ |
283 ASSERT( peer->p_hdr.info.pi_state != STATE_NEW ); | 324 ASSERT( peer->p_hdr.info.runtime.pir_state != STATE_NEW ); |
284 ASSERT( peer->p_hdr.info.pi_state != STATE_ZOMBIE ); | 325 ASSERT( peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE ); |
285 ASSERT( peer->p_hdr.info.pi_state != STATE_OPEN_HANDSHAKE ); /* because it exists only between two loops */ | 326 ASSERT( peer->p_hdr.info.runtime.pir_state != STATE_OPEN_HANDSHAKE ); /* because it exists only between two loops */ |
286 | 327 |
287 /* Purge invalid events */ | 328 /* Purge invalid events */ |
288 if (!CHECK_PEVENT(event)) { | 329 if (!CHECK_PEVENT(event)) { |
289 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); | 330 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); |
290 goto psm_loop; | 331 goto psm_loop; |
296 goto psm_loop; | 337 goto psm_loop; |
297 } | 338 } |
298 | 339 |
299 /* Requests to terminate the peer object */ | 340 /* Requests to terminate the peer object */ |
300 if (event == FDEVP_TERMINATE) { | 341 if (event == FDEVP_TERMINATE) { |
301 switch (peer->p_hdr.info.pi_state) { | 342 switch (peer->p_hdr.info.runtime.pir_state) { |
302 case STATE_OPEN: | 343 case STATE_OPEN: |
303 case STATE_REOPEN: | 344 case STATE_REOPEN: |
304 /* We cannot just close the conenction, we have to send a DPR first */ | 345 /* We cannot just close the conenction, we have to send a DPR first */ |
305 CHECK_FCT_DO( fd_p_dp_initiate(peer), goto psm_end ); | 346 CHECK_FCT_DO( fd_p_dp_initiate(peer), goto psm_end ); |
306 goto psm_loop; | 347 goto psm_loop; |
322 /* A message was received */ | 363 /* A message was received */ |
323 if (event == FDEVP_CNX_MSG_RECV) { | 364 if (event == FDEVP_CNX_MSG_RECV) { |
324 struct msg * msg = NULL; | 365 struct msg * msg = NULL; |
325 struct msg_hdr * hdr; | 366 struct msg_hdr * hdr; |
326 | 367 |
368 /* If the current state does not allow receiving messages, just drop it */ | |
369 if (peer->p_hdr.info.runtime.pir_state == STATE_CLOSED) { | |
370 TRACE_DEBUG(FULL, "Purging message in queue while in CLOSED state (%zdb)", ev_sz); | |
371 free(ev_data); | |
372 goto psm_loop; | |
373 } | |
374 | |
327 /* Parse the received buffer */ | 375 /* Parse the received buffer */ |
328 CHECK_FCT_DO( fd_msg_parse_buffer( (void *)&ev_data, ev_sz, &msg), | 376 CHECK_FCT_DO( fd_msg_parse_buffer( (void *)&ev_data, ev_sz, &msg), |
329 { | 377 { |
330 fd_log_debug("Received invalid data from peer '%s', closing the connection\n", peer->p_hdr.info.pi_diamid); | 378 fd_log_debug("Received invalid data from peer '%s', closing the connection\n", peer->p_hdr.info.pi_diamid); |
331 CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_end ); | 379 CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_end ); |
336 fd_msg_dump_walk(FULL + 1, msg); | 384 fd_msg_dump_walk(FULL + 1, msg); |
337 | 385 |
338 /* Extract the header */ | 386 /* Extract the header */ |
339 CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end ); | 387 CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end ); |
340 | 388 |
341 /* If it is an answer, associate with the request */ | 389 /* If it is an answer, associate with the request or drop */ |
342 if (!(hdr->msg_flags & CMD_FLAG_REQUEST)) { | 390 if (!(hdr->msg_flags & CMD_FLAG_REQUEST)) { |
343 struct msg * req; | 391 struct msg * req; |
344 /* Search matching request (same hbhid) */ | 392 /* Search matching request (same hbhid) */ |
345 CHECK_FCT_DO( fd_p_sr_fetch(&peer->p_sr, hdr->msg_hbhid, &req), goto psm_end ); | 393 CHECK_FCT_DO( fd_p_sr_fetch(&peer->p_sr, hdr->msg_hbhid, &req), goto psm_end ); |
346 if (req == NULL) { | 394 if (req == NULL) { |
347 fd_log_debug("Received a Diameter answer message with no corresponding sent request, discarding...\n"); | 395 fd_log_debug("Received a Diameter answer message with no corresponding sent request, discarding.\n"); |
348 fd_msg_dump_walk(NONE, msg); | 396 fd_msg_dump_walk(NONE, msg); |
349 fd_msg_free(msg); | 397 fd_msg_free(msg); |
350 goto psm_loop; | 398 goto psm_loop; |
351 } | 399 } |
352 | 400 |
354 CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end ); | 402 CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end ); |
355 } | 403 } |
356 | 404 |
357 /* Now handle non-link-local messages */ | 405 /* Now handle non-link-local messages */ |
358 if (fd_msg_is_routable(msg)) { | 406 if (fd_msg_is_routable(msg)) { |
359 /* If we are not in OPEN state, discard the message */ | 407 switch (peer->p_hdr.info.runtime.pir_state) { |
360 if (peer->p_hdr.info.pi_state != STATE_OPEN) { | 408 /* To maximize compatibility -- should not be a security issue here */ |
361 fd_log_debug("Received a routable message while not in OPEN state from peer '%s', discarded.\n", peer->p_hdr.info.pi_diamid); | 409 case STATE_REOPEN: |
362 fd_msg_dump_walk(NONE, msg); | 410 case STATE_SUSPECT: |
363 fd_msg_free(msg); | 411 case STATE_CLOSING: |
364 } else { | 412 TRACE_DEBUG(FULL, "Accepted a message while not in OPEN state"); |
365 /* We received a valid message, update the expiry timer */ | 413 /* The standard situation : */ |
366 CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end ); | 414 case STATE_OPEN: |
367 | 415 /* We received a valid message, update the expiry timer */ |
368 /* Set the message source and add the Route-Record */ | 416 CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end ); |
369 CHECK_FCT_DO( fd_msg_source_set( msg, peer->p_hdr.info.pi_diamid, 1, fd_g_config->cnf_dict ), goto psm_end); | 417 |
370 | 418 /* Set the message source and add the Route-Record */ |
371 /* Requeue to the global incoming queue */ | 419 CHECK_FCT_DO( fd_msg_source_set( msg, peer->p_hdr.info.pi_diamid, 1, fd_g_config->cnf_dict ), goto psm_end); |
372 CHECK_FCT_DO(fd_fifo_post(fd_g_incoming, &msg), goto psm_end ); | 420 |
373 | 421 /* Requeue to the global incoming queue */ |
374 /* Update the peer timer */ | 422 CHECK_FCT_DO(fd_fifo_post(fd_g_incoming, &msg), goto psm_end ); |
375 if (!peer->p_flags.pf_dw_pending) { | 423 |
376 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_twtimer ?: fd_g_config->cnf_timer_tw); | 424 /* Update the peer timer (only in OPEN state) */ |
377 } | 425 if ((peer->p_hdr.info.runtime.pir_state == STATE_OPEN) && (!peer->p_flags.pf_dw_pending)) { |
426 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw); | |
427 } | |
428 break; | |
429 | |
430 /* In other states, we discard the message, it is either old or invalid to send it for the remote peer */ | |
431 case STATE_WAITCNXACK: | |
432 case STATE_WAITCNXACK_ELEC: | |
433 case STATE_WAITCEA: | |
434 case STATE_CLOSED: | |
435 default: | |
436 /* In such case, just discard the message */ | |
437 fd_log_debug("Received a routable message while not in OPEN state from peer '%s', discarded.\n", peer->p_hdr.info.pi_diamid); | |
438 fd_msg_dump_walk(NONE, msg); | |
439 fd_msg_free(msg); | |
378 } | 440 } |
379 goto psm_loop; | 441 goto psm_loop; |
380 } | 442 } |
381 | 443 |
382 /* Link-local message: They must be understood by our dictionary */ | 444 /* Link-local message: They must be understood by our dictionary, otherwise we return an error */ |
383 { | 445 { |
384 int ret; | 446 int ret; |
385 CHECK_FCT_DO( ret = fd_msg_parse_or_error( &msg ), | 447 CHECK_FCT_DO( ret = fd_msg_parse_or_error( &msg ), |
386 { | 448 { |
387 if ((ret == EBADMSG) && (msg != NULL)) { | 449 if ((ret == EBADMSG) && (msg != NULL)) { |
393 } | 455 } |
394 goto psm_loop; | 456 goto psm_loop; |
395 } ); | 457 } ); |
396 } | 458 } |
397 | 459 |
398 ASSERT( hdr->msg_appl == 0 ); /* buggy fd_msg_is_routable() ? */ | |
399 | |
400 /* Handle the LL message and update the expiry timer appropriately */ | 460 /* Handle the LL message and update the expiry timer appropriately */ |
401 switch (hdr->msg_code) { | 461 switch (hdr->msg_code) { |
402 case CC_DEVICE_WATCHDOG: | 462 case CC_CAPABILITIES_EXCHANGE: |
403 CHECK_FCT_DO( fd_p_dw_handle(&msg, peer), goto psm_end ); | 463 CHECK_FCT_DO( fd_p_ce_handle(&msg, peer), goto psm_end ); |
404 break; | 464 break; |
405 | 465 |
406 case CC_DISCONNECT_PEER: | 466 case CC_DISCONNECT_PEER: |
407 CHECK_FCT_DO( fd_p_dp_handle(&msg, peer), goto psm_end ); | 467 CHECK_FCT_DO( fd_p_dp_handle(&msg, peer), goto psm_end ); |
408 break; | 468 break; |
409 | 469 |
410 case CC_CAPABILITIES_EXCHANGE: | 470 case CC_DEVICE_WATCHDOG: |
411 CHECK_FCT_DO( fd_p_ce_handle(&msg, peer), goto psm_end ); | 471 CHECK_FCT_DO( fd_p_dw_handle(&msg, peer), goto psm_end ); |
412 break; | 472 break; |
413 | 473 |
414 default: | 474 default: |
415 /* Unknown / unexpected / invalid message */ | 475 /* Unknown / unexpected / invalid message */ |
416 TODO("Log, return error message if request"); | 476 fd_log_debug("Received an unknown local message from peer '%s', discarded.\n", peer->p_hdr.info.pi_diamid); |
477 fd_msg_dump_walk(NONE, msg); | |
478 if (hdr->msg_flags & CMD_FLAG_REQUEST) { | |
479 do { | |
480 /* Reply with an error code */ | |
481 CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, MSGFL_ANSW_ERROR ), break ); | |
482 | |
483 /* Set the error code */ | |
484 CHECK_FCT_DO( fd_msg_rescode_set(msg, "DIAMETER_INVALID_HDR_BITS", NULL, NULL, 1 ), break ); | |
485 | |
486 /* Send the answer */ | |
487 CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer), break ); | |
488 } while (0); | |
489 } else { | |
490 /* We did ASK for it ??? */ | |
491 fd_log_debug("Invalid PXY flag in header ?\n"); | |
492 } | |
493 | |
494 /* Cleanup the message if not done */ | |
495 if (msg) { | |
496 CHECK_FCT_DO( fd_msg_free(msg), /* continue */); | |
497 msg = NULL; | |
498 } | |
417 }; | 499 }; |
418 | 500 |
419 /* At this point the message must have been fully handled already */ | 501 /* At this point the message must have been fully handled already */ |
420 if (msg) { | 502 if (msg) { |
421 fd_log_debug("Internal error: unhandled message (discarded)!\n"); | 503 fd_log_debug("Internal error: unhandled message (discarded)!\n"); |
426 goto psm_loop; | 508 goto psm_loop; |
427 } | 509 } |
428 | 510 |
429 /* The connection object is broken */ | 511 /* The connection object is broken */ |
430 if (event == FDEVP_CNX_ERROR) { | 512 if (event == FDEVP_CNX_ERROR) { |
431 /* Cleanup the peer */ | 513 switch (peer->p_hdr.info.runtime.pir_state) { |
432 fd_psm_cleanup(peer); | 514 case STATE_WAITCNXACK_ELEC: |
433 | 515 TODO("Reply CEA on the receiver side and go to OPEN state"); |
434 /* Mark the connection problem */ | 516 goto psm_loop; |
435 peer->p_flags.pf_cnx_pb = 1; | 517 |
436 | 518 case STATE_OPEN: |
437 /* Move to CLOSED */ | 519 case STATE_REOPEN: |
438 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end ); | 520 case STATE_WAITCNXACK: |
439 | 521 case STATE_WAITCEA: |
440 /* Reset the timer */ | 522 case STATE_SUSPECT: |
441 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc); | 523 default: |
442 | 524 /* Mark the connection problem */ |
443 /* Loop */ | 525 peer->p_flags.pf_cnx_pb = 1; |
444 goto psm_loop; | 526 |
527 case STATE_CLOSING: | |
528 /* Cleanup the peer */ | |
529 fd_psm_cleanup(peer); | |
530 | |
531 /* Reset the timer */ | |
532 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc); | |
533 | |
534 case STATE_CLOSED: | |
535 /* Go to the next event */ | |
536 goto psm_loop; | |
537 } | |
445 } | 538 } |
446 | 539 |
447 /* The connection notified a change in endpoints */ | 540 /* The connection notified a change in endpoints */ |
448 if (event == FDEVP_CNX_EP_CHANGE) { | 541 if (event == FDEVP_CNX_EP_CHANGE) { |
542 /* We actually don't care if we are in OPEN state here... */ | |
543 | |
449 /* Cleanup the remote LL and primary addresses */ | 544 /* Cleanup the remote LL and primary addresses */ |
450 CHECK_FCT_DO( fd_ep_filter( &peer->p_hdr.info.pi_endpoints, EP_FL_CONF | EP_FL_DISC | EP_FL_ADV ), /* ignore the error */); | 545 CHECK_FCT_DO( fd_ep_filter( &peer->p_hdr.info.pi_endpoints, EP_FL_CONF | EP_FL_DISC | EP_FL_ADV ), /* ignore the error */); |
451 CHECK_FCT_DO( fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_PRIMARY ), /* ignore the error */); | 546 CHECK_FCT_DO( fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_PRIMARY ), /* ignore the error */); |
452 | 547 |
453 /* Get the new ones */ | 548 /* Get the new ones */ |
454 CHECK_FCT_DO( fd_cnx_getendpoints(peer->p_cnxctx, NULL, &peer->p_hdr.info.pi_endpoints), /* ignore the error */); | 549 CHECK_FCT_DO( fd_cnx_getendpoints(peer->p_cnxctx, NULL, &peer->p_hdr.info.pi_endpoints), /* ignore the error */); |
455 | 550 |
551 /* We do not support local endpoints change currently, but it could be added here if needed */ | |
552 | |
456 if (TRACE_BOOL(ANNOYING)) { | 553 if (TRACE_BOOL(ANNOYING)) { |
457 fd_log_debug("New remote endpoint(s):\n"); | 554 TRACE_DEBUG(ANNOYING, "New remote endpoint(s):" ); |
458 fd_ep_dump(6, &peer->p_hdr.info.pi_endpoints); | 555 fd_ep_dump(6, &peer->p_hdr.info.pi_endpoints); |
459 } | 556 } |
460 | 557 |
461 /* Done */ | 558 /* Done */ |
462 goto psm_loop; | 559 goto psm_loop; |
485 goto psm_loop; | 582 goto psm_loop; |
486 } | 583 } |
487 | 584 |
488 /* The timeout for the current state has been reached */ | 585 /* The timeout for the current state has been reached */ |
489 if (event == FDEVP_PSM_TIMEOUT) { | 586 if (event == FDEVP_PSM_TIMEOUT) { |
490 switch (peer->p_hdr.info.pi_state) { | 587 switch (peer->p_hdr.info.runtime.pir_state) { |
491 case STATE_OPEN: | 588 case STATE_OPEN: |
492 case STATE_REOPEN: | 589 case STATE_REOPEN: |
493 CHECK_FCT_DO( fd_p_dw_timeout(peer), goto psm_end ); | 590 CHECK_FCT_DO( fd_p_dw_timeout(peer), goto psm_end ); |
494 break; | 591 break; |
495 | 592 |
496 case STATE_CLOSED: | 593 case STATE_CLOSED: |
497 TODO("Initiate a new connection"); | 594 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_WAITCNXACK), goto psm_end ); |
595 fd_psm_next_timeout(peer, 0, CNX_TIMEOUT); | |
596 CHECK_FCT_DO( fd_p_cnx_init(peer), goto psm_end ); | |
498 break; | 597 break; |
499 | 598 |
500 case STATE_CLOSING: | 599 case STATE_CLOSING: |
501 case STATE_SUSPECT: | 600 case STATE_SUSPECT: |
502 case STATE_WAITCNXACK: | 601 case STATE_WAITCNXACK: |
503 case STATE_WAITCEA: | 602 case STATE_WAITCEA: |
504 /* Destroy the connection, restart the timer to a new connection attempt */ | 603 /* Destroy the connection, restart the timer to a new connection attempt */ |
505 fd_psm_cleanup(peer); | 604 fd_psm_cleanup(peer); |
506 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc); | 605 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc); |
507 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end ); | |
508 break; | 606 break; |
509 | 607 |
510 case STATE_WAITCNXACK_ELEC: | 608 case STATE_WAITCNXACK_ELEC: |
511 TODO("Abort initiating side, handle the receiver side"); | 609 TODO("Abort initiating side, handle the receiver side"); |
512 break; | 610 break; |
513 } | 611 } |
514 } | 612 } |
515 | 613 |
516 /* Default action : the handling has not yet been implemented. [for debug only] */ | 614 /* Default action : the handling has not yet been implemented. [for debug only] */ |
517 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event)); | 615 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.runtime.pir_state), fd_pev_str(event)); |
518 if (event == FDEVP_PSM_TIMEOUT) { | 616 if (event == FDEVP_PSM_TIMEOUT) { |
519 /* We have not handled timeout in this state, let's postpone next alert */ | 617 /* We have not handled timeout in this state, let's postpone next alert */ |
520 fd_psm_next_timeout(peer, 0, 60); | 618 fd_psm_next_timeout(peer, 0, 60); |
521 } | 619 } |
522 | 620 |
523 goto psm_loop; | 621 goto psm_loop; |
524 | 622 |
525 psm_end: | 623 psm_end: |
526 fd_psm_cleanup(peer); | 624 fd_psm_cleanup(peer); |
625 CHECK_FCT_DO( fd_fifo_del(&peer->p_events), /* continue */ ); | |
527 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ | 626 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ |
528 peer->p_psm = (pthread_t)NULL; | 627 peer->p_psm = (pthread_t)NULL; |
529 pthread_detach(pthread_self()); | 628 pthread_detach(pthread_self()); |
530 return NULL; | 629 return NULL; |
531 } | 630 } |
538 int fd_psm_begin(struct fd_peer * peer ) | 637 int fd_psm_begin(struct fd_peer * peer ) |
539 { | 638 { |
540 TRACE_ENTRY("%p", peer); | 639 TRACE_ENTRY("%p", peer); |
541 | 640 |
542 /* Check the peer and state are OK */ | 641 /* Check the peer and state are OK */ |
543 CHECK_PARAMS( CHECK_PEER(peer) && (peer->p_hdr.info.pi_state == STATE_NEW) ); | 642 CHECK_PARAMS( CHECK_PEER(peer) && (peer->p_hdr.info.runtime.pir_state == STATE_NEW) ); |
643 | |
644 /* Create the FIFO for events */ | |
645 CHECK_FCT( fd_fifo_new(&peer->p_events) ); | |
544 | 646 |
545 /* Create the PSM controler thread */ | 647 /* Create the PSM controler thread */ |
546 CHECK_POSIX( pthread_create( &peer->p_psm, NULL, p_psm_th, peer ) ); | 648 CHECK_POSIX( pthread_create( &peer->p_psm, NULL, p_psm_th, peer ) ); |
547 | 649 |
548 /* We're done */ | 650 /* We're done */ |
553 int fd_psm_terminate(struct fd_peer * peer ) | 655 int fd_psm_terminate(struct fd_peer * peer ) |
554 { | 656 { |
555 TRACE_ENTRY("%p", peer); | 657 TRACE_ENTRY("%p", peer); |
556 CHECK_PARAMS( CHECK_PEER(peer) ); | 658 CHECK_PARAMS( CHECK_PEER(peer) ); |
557 | 659 |
558 if (peer->p_hdr.info.pi_state != STATE_ZOMBIE) { | 660 if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE) { |
559 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) ); | 661 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) ); |
560 } else { | 662 } else { |
561 TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid); | 663 TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid); |
562 } | 664 } |
563 return 0; | 665 return 0; |
569 TRACE_ENTRY("%p", peer); | 671 TRACE_ENTRY("%p", peer); |
570 | 672 |
571 /* Cancel PSM thread */ | 673 /* Cancel PSM thread */ |
572 CHECK_FCT_DO( fd_thr_term(&peer->p_psm), /* continue */ ); | 674 CHECK_FCT_DO( fd_thr_term(&peer->p_psm), /* continue */ ); |
573 | 675 |
574 /* Cancel the OUT thread */ | 676 /* Cleanup the data */ |
575 CHECK_FCT_DO( fd_out_stop(peer), /* continue */ ); | 677 fd_psm_cleanup(peer); |
576 | 678 |
577 /* Cleanup the connection */ | 679 /* Destroy the event list */ |
578 if (peer->p_cnxctx) { | 680 CHECK_FCT_DO( fd_fifo_del(&peer->p_events), /* continue */ ); |
579 fd_cnx_destroy(peer->p_cnxctx); | 681 |
580 } | 682 /* Remaining cleanups are performed in fd_peer_free */ |
581 | |
582 /* Failover the messages */ | |
583 fd_peer_failover_msg(peer); | |
584 | |
585 /* Empty the events list, this might leak some memory, but we only do it on exit, so... */ | |
586 fd_event_destroy(&peer->p_events, free); | |
587 | |
588 /* More cleanups are performed in fd_peer_free */ | |
589 return; | 683 return; |
590 } | 684 } |
591 | 685 |