comparison freeDiameter/p_psm.c @ 36:1498b3c7304c

Backup
author Sebastien Decugis <sdecugis@nict.go.jp>
date Mon, 02 Nov 2009 17:31:36 +0900
parents 6486e97f56ae
children cc3c59fe98fe
comparison
equal deleted inserted replaced
35:6486e97f56ae 36:1498b3c7304c
143 143
144 /************************************************************************/ 144 /************************************************************************/
145 /* Helpers for state changes */ 145 /* Helpers for state changes */
146 /************************************************************************/ 146 /************************************************************************/
147 /* Change state */ 147 /* Change state */
148 static int change_state(struct fd_peer * peer, int new_state) 148 int fd_psm_change_state(struct fd_peer * peer, int new_state)
149 { 149 {
150 int old; 150 int old;
151 151
152 TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state)); 152 TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state));
153 CHECK_PARAMS( CHECK_PEER(peer) ); 153 CHECK_PARAMS( CHECK_PEER(peer) );
168 168
169 if (new_state == STATE_OPEN) { 169 if (new_state == STATE_OPEN) {
170 CHECK_FCT( enter_open_state(peer) ); 170 CHECK_FCT( enter_open_state(peer) );
171 } 171 }
172 172
173 if ((new_state == STATE_CLOSED) && (peer->p_hdr.info.pi_flags.persist == PI_PRST_NONE)) {
174 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) );
175 }
176
173 return 0; 177 return 0;
174 } 178 }
175 179
176 /* Set timeout timer of next event */ 180 /* Set timeout timer of next event */
177 static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay) 181 void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
178 { 182 {
179 /* Initialize the timer */ 183 /* Initialize the timer */
180 CHECK_POSIX_DO( clock_gettime( CLOCK_REALTIME, &peer->p_psm_timer ), ASSERT(0) ); 184 CHECK_POSIX_DO( clock_gettime( CLOCK_REALTIME, &peer->p_psm_timer ), ASSERT(0) );
181 185
182 if (add_random) { 186 if (add_random) {
200 /* temporary for debug */ 204 /* temporary for debug */
201 peer->p_psm_timer.tv_sec += 10; 205 peer->p_psm_timer.tv_sec += 10;
202 #endif 206 #endif
203 } 207 }
204 208
209 /* Cleanup the peer */
210 void fd_psm_cleanup(struct fd_peer * peer)
211 {
212 /* Move to CLOSED state */
213 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ );
214
215 /* Destroy the connection */
216 if (peer->p_cnxctx) {
217 fd_cnx_destroy(peer->p_cnxctx);
218 peer->p_cnxctx = NULL;
219 }
220
221 /* What else ? */
222 TODO("...");
223
224 }
225
205 226
206 /************************************************************************/ 227 /************************************************************************/
207 /* The PSM thread */ 228 /* The PSM thread */
208 /************************************************************************/ 229 /************************************************************************/
209 /* Cancelation cleanup : set ZOMBIE state in the peer */ 230 /* Cancelation cleanup : set ZOMBIE state in the peer */
210 void cleanup_state(void * arg) 231 void cleanup_setstate(void * arg)
211 { 232 {
212 struct fd_peer * peer = (struct fd_peer *)arg; 233 struct fd_peer * peer = (struct fd_peer *)arg;
213 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); 234 CHECK_PARAMS_DO( CHECK_PEER(peer), return );
214 peer->p_hdr.info.pi_state = STATE_ZOMBIE; 235 peer->p_hdr.info.pi_state = STATE_ZOMBIE;
215 return; 236 return;
224 size_t ev_sz; 245 size_t ev_sz;
225 void * ev_data; 246 void * ev_data;
226 247
227 CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) ); 248 CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) );
228 249
229 pthread_cleanup_push( cleanup_state, arg ); 250 pthread_cleanup_push( cleanup_setstate, arg );
230 251
231 /* Set the thread name */ 252 /* Set the thread name */
232 { 253 {
233 char buf[48]; 254 char buf[48];
234 sprintf(buf, "PSM/%.*s", sizeof(buf) - 5, peer->p_hdr.info.pi_diamid); 255 sprintf(buf, "PSM/%.*s", sizeof(buf) - 5, peer->p_hdr.info.pi_diamid);
241 /* Wait that the PSM are authorized to start in the daemon */ 262 /* Wait that the PSM are authorized to start in the daemon */
242 CHECK_FCT_DO( fd_psm_waitstart(), goto psm_end ); 263 CHECK_FCT_DO( fd_psm_waitstart(), goto psm_end );
243 264
244 /* Initialize the timer */ 265 /* Initialize the timer */
245 if (peer->p_flags.pf_responder) { 266 if (peer->p_flags.pf_responder) {
246 psm_next_timeout(peer, 0, INCNX_TIMEOUT); 267 fd_psm_next_timeout(peer, 0, INCNX_TIMEOUT);
247 } else { 268 } else {
248 psm_next_timeout(peer, created_started, 0); 269 fd_psm_next_timeout(peer, created_started, 0);
249 } 270 }
250 271
251 psm_loop: 272 psm_loop:
252 /* Get next event */ 273 /* Get next event */
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 ); 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 );
276 } 297 }
277 298
278 /* Requests to terminate the peer object */ 299 /* Requests to terminate the peer object */
279 if (event == FDEVP_TERMINATE) { 300 if (event == FDEVP_TERMINATE) {
280 switch (peer->p_hdr.info.pi_state) { 301 switch (peer->p_hdr.info.pi_state) {
302 case STATE_OPEN:
303 case STATE_REOPEN:
304 /* 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 );
306 goto psm_loop;
307
308 /*
281 case STATE_CLOSING: 309 case STATE_CLOSING:
282 case STATE_WAITCNXACK: 310 case STATE_WAITCNXACK:
283 case STATE_WAITCNXACK_ELEC: 311 case STATE_WAITCNXACK_ELEC:
284 case STATE_WAITCEA: 312 case STATE_WAITCEA:
285 case STATE_SUSPECT: 313 case STATE_SUSPECT:
286 /* In these cases, we just cleanup the peer object and terminate now */
287 TODO("Cleanup the PSM: terminate connection object, ...");
288 case STATE_CLOSED: 314 case STATE_CLOSED:
289 /* Then we just terminate the PSM */ 315 */
316 default:
317 /* In these cases, we just cleanup the peer object (if needed) and terminate */
290 goto psm_end; 318 goto psm_end;
291
292 case STATE_OPEN:
293 case STATE_REOPEN:
294 /* We cannot just close the conenction, we have to send a DPR first */
295 TODO("Send DPR, mark the peer as CLOSING");
296 goto psm_loop;
297 } 319 }
298 } 320 }
299 321
300 /* A message was received */ 322 /* A message was received */
301 if (event == FDEVP_CNX_MSG_RECV) { 323 if (event == FDEVP_CNX_MSG_RECV) {
308 fd_log_debug("Received invalid data from peer '%s', closing the connection\n", peer->p_hdr.info.pi_diamid); 330 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 ); 331 CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_end );
310 goto psm_loop; 332 goto psm_loop;
311 } ); 333 } );
312 334
313 TRACE_DEBUG(FULL, "Received this message from '%s':", peer->p_hdr.info.pi_diamid); 335 TRACE_DEBUG(FULL, "Received a message (%zdb) from '%s'", ev_sz, peer->p_hdr.info.pi_diamid);
314 fd_msg_dump_walk(FULL, msg); 336 fd_msg_dump_walk(FULL + 1, msg);
315 337
316 /* Extract the header */ 338 /* Extract the header */
317 CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end ); 339 CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end );
318 340
319 /* If it is an answer, associate with the request */ 341 /* If it is an answer, associate with the request */
330 352
331 /* Associate */ 353 /* Associate */
332 CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end ); 354 CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end );
333 } 355 }
334 356
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 */ 357 /* Now handle non-link-local messages */
339 if (fd_msg_is_routable(msg)) { 358 if (fd_msg_is_routable(msg)) {
340 /* If we are not in OPEN state, discard the message */ 359 /* If we are not in OPEN state, discard the message */
341 if (peer->p_hdr.info.pi_state != STATE_OPEN) { 360 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); 361 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); 362 fd_msg_dump_walk(NONE, msg);
344 fd_msg_free(msg); 363 fd_msg_free(msg);
345 } else { 364 } else {
365 /* We received a valid message, update the expiry timer */
366 CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end );
367
346 /* Set the message source and add the Route-Record */ 368 /* 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); 369 CHECK_FCT_DO( fd_msg_source_set( msg, peer->p_hdr.info.pi_diamid, 1, fd_g_config->cnf_dict ), goto psm_end);
348 370
349 /* Requeue to the global incoming queue */ 371 /* Requeue to the global incoming queue */
350 CHECK_FCT_DO(fd_fifo_post(fd_g_incoming, &msg), goto psm_end ); 372 CHECK_FCT_DO(fd_fifo_post(fd_g_incoming, &msg), goto psm_end );
351 373
352 /* Update the peer timer */ 374 /* Update the peer timer */
353 if (!peer->p_flags.pf_dw_pending) { 375 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); 376 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_twtimer ?: fd_g_config->cnf_timer_tw);
355 } 377 }
356 } 378 }
357 goto psm_loop; 379 goto psm_loop;
358 } 380 }
359 381
371 } 393 }
372 goto psm_loop; 394 goto psm_loop;
373 } ); 395 } );
374 } 396 }
375 397
398 ASSERT( hdr->msg_appl == 0 ); /* buggy fd_msg_is_routable() ? */
399
376 /* Handle the LL message and update the expiry timer appropriately */ 400 /* Handle the LL message and update the expiry timer appropriately */
377 TODO("..."); 401 switch (hdr->msg_code) {
402 case CC_DEVICE_WATCHDOG:
403 CHECK_FCT_DO( fd_p_dw_handle(&msg, peer), goto psm_end );
404 break;
405
406 case CC_DISCONNECT_PEER:
407 CHECK_FCT_DO( fd_p_dp_handle(&msg, peer), goto psm_end );
408 break;
409
410 case CC_CAPABILITIES_EXCHANGE:
411 CHECK_FCT_DO( fd_p_ce_handle(&msg, peer), goto psm_end );
412 break;
413
414 default:
415 /* Unknown / unexpected / invalid message */
416 TODO("Log, return error message if request");
417 };
418
419 /* At this point the message must have been fully handled already */
420 if (msg) {
421 fd_log_debug("Internal error: unhandled message (discarded)!\n");
422 fd_msg_dump_walk(NONE, msg);
423 fd_msg_free(msg);
424 }
425
426 goto psm_loop;
378 } 427 }
379 428
380 /* The connection object is broken */ 429 /* The connection object is broken */
381 if (event == FDEVP_CNX_ERROR) { 430 if (event == FDEVP_CNX_ERROR) {
382 TODO("Destroy the connection object"); 431 /* Cleanup the peer */
383 TODO("Mark the error in the peer (pf_cnx_pb)"); 432 fd_psm_cleanup(peer);
384 TODO("Move to closed state, Requeue all messages to a different connection (failover)"); 433
385 TODO("If pi_flags.exp, terminate the peer"); 434 /* Mark the connection problem */
435 peer->p_flags.pf_cnx_pb = 1;
436
437 /* Move to CLOSED */
438 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end );
439
440 /* Reset the timer */
441 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc);
442
443 /* Loop */
444 goto psm_loop;
386 } 445 }
387 446
388 /* The connection notified a change in endpoints */ 447 /* The connection notified a change in endpoints */
389 if (event == FDEVP_CNX_EP_CHANGE) { 448 if (event == FDEVP_CNX_EP_CHANGE) {
390 /* Cleanup the remote LL and primary addresses */ 449 /* Cleanup the remote LL and primary addresses */
406 /* A new connection was established and CER containing this peer id was received */ 465 /* A new connection was established and CER containing this peer id was received */
407 if (event == FDEVP_CNX_INCOMING) { 466 if (event == FDEVP_CNX_INCOMING) {
408 struct cnx_incoming * params = ev_data; 467 struct cnx_incoming * params = ev_data;
409 ASSERT(params); 468 ASSERT(params);
410 469
411 switch (peer->p_hdr.info.pi_state) { 470 /* Handle the message */
412 case STATE_CLOSED: 471 CHECK_FCT_DO( fd_p_ce_handle_newCER(&params->cer, peer, &params->cnx, params->validate), goto psm_end );
413 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"); 472
414 /* In case of error : DIAMETER_UNKNOWN_PEER */ 473 /* Cleanup if needed */
415 474 if (params->cnx) {
416 CHECK_FCT_DO( fd_p_ce_merge(peer, params->cer), 475 fd_cnx_destroy(params->cnx);
417 { 476 params->cnx = NULL;
418 477 }
419 } ); 478 if (params->cer) {
420 479 CHECK_FCT_DO( fd_msg_free(params->cer), );
421 break; 480 params->cer = NULL;
422 481 }
423 case STATE_WAITCNXACK: 482
424 case STATE_WAITCEA: 483 /* Loop */
425 TODO("Election");
426 break;
427
428 default:
429 TODO("Reply with error CEA");
430 TODO("Close the connection");
431 /* reject_incoming_connection */
432
433 }
434
435 free(ev_data); 484 free(ev_data);
436 goto psm_loop; 485 goto psm_loop;
437 } 486 }
438 487
439 /* The timeout for the current state has been reached */ 488 /* The timeout for the current state has been reached */
440 if (event == FDEVP_PSM_TIMEOUT) { 489 if (event == FDEVP_PSM_TIMEOUT) {
441 switch (peer->p_hdr.info.pi_state) { 490 switch (peer->p_hdr.info.pi_state) {
442 491 case STATE_OPEN:
443 492 case STATE_REOPEN:
493 CHECK_FCT_DO( fd_p_dw_timeout(peer), goto psm_end );
494 break;
495
496 case STATE_CLOSED:
497 TODO("Initiate a new connection");
498 break;
499
500 case STATE_CLOSING:
501 case STATE_SUSPECT:
502 case STATE_WAITCNXACK:
503 case STATE_WAITCEA:
504 /* Destroy the connection, restart the timer to a new connection attempt */
505 fd_psm_cleanup(peer);
506 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc);
507 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end );
508 break;
509
510 case STATE_WAITCNXACK_ELEC:
511 TODO("Abort initiating side, handle the receiver side");
512 break;
444 } 513 }
445 } 514 }
446 515
447 /* Default action : the handling has not yet been implemented. [for debug only] */ 516 /* Default action : the handling has not yet been implemented. [for debug only] */
448 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event)); 517 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event));
449 if (event == FDEVP_PSM_TIMEOUT) { 518 if (event == FDEVP_PSM_TIMEOUT) {
450 /* We have not handled timeout in this state, let's postpone next alert */ 519 /* We have not handled timeout in this state, let's postpone next alert */
451 psm_next_timeout(peer, 0, 60); 520 fd_psm_next_timeout(peer, 0, 60);
452 } 521 }
453 522
454 goto psm_loop; 523 goto psm_loop;
455 524
456 psm_end: 525 psm_end:
526 fd_psm_cleanup(peer);
457 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ 527 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */
458 peer->p_psm = (pthread_t)NULL; 528 peer->p_psm = (pthread_t)NULL;
459 pthread_detach(pthread_self()); 529 pthread_detach(pthread_self());
460 return NULL; 530 return NULL;
461 } 531 }
"Welcome to our mercurial repository"