changeset 79:d273a2ce19c8

Fix problem in DPR handling
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 02 Dec 2009 10:25:59 +0900
parents a58f0757c06a
children 56f0b629e036
files freeDiameter/p_dp.c freeDiameter/p_psm.c
diffstat 2 files changed, 29 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/p_dp.c	Tue Dec 01 16:24:06 2009 +0900
+++ b/freeDiameter/p_dp.c	Wed Dec 02 10:25:59 2009 +0900
@@ -40,12 +40,12 @@
 /* Handle a received message */
 int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer)
 {
-	int delay = 0;
 	TRACE_ENTRY("%p %d %p", msg, req, peer);
 	
 	if (req) {
 		/* We received a DPR, save the Disconnect-Cause and terminate the connection */
 		struct avp * dc;
+		int delay = peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc;
 		
 		CHECK_FCT_DO( fd_msg_search_avp ( *msg, fd_dict_avp_DC, &dc ), return );
 		if (dc) {
@@ -60,6 +60,21 @@
 			}
 
 			peer->p_hdr.info.runtime.pir_lastDC = hdr->avp_value->u32;
+			
+			switch (hdr->avp_value->u32) {
+				case ACV_DC_REBOOTING:
+				default:
+					/* We use TcTimer to attempt reconnection */
+					break;
+				case ACV_DC_BUSY:
+					/* No need to hammer the overloaded peer */
+					delay *= 10;
+					break;
+				case ACV_DC_NOT_FRIEND:
+					/* He does not want to speak to us... let's retry a lot later maybe */
+					delay *= 200;
+					break;
+			}
 		}
 		if (TRACE_BOOL(INFO)) {
 			if (dc) {
@@ -91,21 +106,25 @@
 		/* Now send the DPA */
 		CHECK_FCT( fd_out_send( msg, NULL, peer) );
 		
+		/* Move to CLOSED state */
+		fd_psm_cleanup(peer, 0);
+		
+		/* Reset the timer for next connection attempt -- we'll retry sooner or later depending on the disconnection cause */
+		fd_psm_next_timeout(peer, 1, delay);
+		
 	} else {
 		/* We received a DPA */
 		if (peer->p_hdr.info.runtime.pir_state != STATE_CLOSING) {
 			TRACE_DEBUG(INFO, "Ignore DPA received in state %s", STATE_STR(peer->p_hdr.info.runtime.pir_state));
 		}
 			
+		/* In theory, we should control the Result-Code AVP. But since we will not go back to OPEN state here anyway, let's skip it */
+		CHECK_FCT_DO( fd_msg_free( *msg ), /* continue */ );
+		*msg = NULL;
+		
+		/* The calling function handles cleaning the PSM and terminating the peer since we return in CLOSING state */
 	}
 	
-	if (*msg) {
-		/* In theory, we should control the Result-Code AVP. But since we will not go back to OPEN state here, let's skip it */
-		CHECK_FCT_DO( fd_msg_free( *msg ), /* continue */ );
-		*msg = NULL;
-	}
-	
-	/* The calling function handles cleaning the PSM and terminating the peer */
 	return 0;
 }
 
--- a/freeDiameter/p_psm.c	Tue Dec 01 16:24:06 2009 +0900
+++ b/freeDiameter/p_psm.c	Wed Dec 02 10:25:59 2009 +0900
@@ -538,11 +538,8 @@
 				peer->p_flags.pf_cnx_pb = 1;
 				
 			case STATE_CLOSING:
-				/* Cleanup the peer */
-				fd_psm_cleanup(peer, 0);
-
-				/* Reset the timer */
-				fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc);
+				/* We sent a DPR so we are terminating, do not wait for DPA */
+				goto psm_end;
 				
 			case STATE_CLOSED:
 				/* Just ignore */
"Welcome to our mercurial repository"