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
"Welcome to our mercurial repository"