comparison libfdcore/p_dw.c @ 706:4ffbc9f1e922

Large UNTESTED commit with the following changes: * Improved DiameterIdentity handling (esp. interationalization issues), and improve efficiency of some string operations in peers, sessions, and dictionary modules (closes #7) * Cleanup in the session module to free only unreferenced sessions (#16) * Removed fd_cpu_flush_cache(), replaced by more robust alternatives. * Improved peer state machine algorithm to counter SCTP multistream race condition.
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 09 Feb 2011 15:26:58 +0900
parents 2e94ef0515d7
children 4a9f08d6b6ba
comparison
equal deleted inserted replaced
705:f0cb8f465763 706:4ffbc9f1e922
35 35
36 #include "fdcore-internal.h" 36 #include "fdcore-internal.h"
37 37
38 /* This file contains code to handle Device Watchdog messages (DWR and DWA) */ 38 /* This file contains code to handle Device Watchdog messages (DWR and DWA) */
39 39
40 /* Check the value of Origin-State-Id is consistent in a DWR or DWA -- we just log if it is not the case */ 40 /* Check the value of Origin-State-Id is consistent in a DWR or DWA -- we return an error otherwise */
41 static void check_state_id(struct msg * msg, struct fd_peer * peer) 41 static int check_state_id(struct msg * msg, struct fd_peer * peer)
42 { 42 {
43 struct avp * osi; 43 struct avp * osi;
44
44 /* Check if the request contains the Origin-State-Id */ 45 /* Check if the request contains the Origin-State-Id */
45 CHECK_FCT_DO( fd_msg_search_avp ( msg, fd_dict_avp_OSI, &osi ), return ); 46 CHECK_FCT( fd_msg_search_avp ( msg, fd_dict_avp_OSI, &osi ) );
46 if (osi) { 47 if (osi) {
47 /* Check the value is consistent with the saved one */ 48 /* Check the value is consistent with the saved one */
48 struct avp_hdr * hdr; 49 struct avp_hdr * hdr;
49 CHECK_FCT_DO( fd_msg_avp_hdr( osi, &hdr ), return ); 50 CHECK_FCT( fd_msg_avp_hdr( osi, &hdr ) );
50 if (hdr->avp_value == NULL) { 51 if (hdr->avp_value == NULL) {
51 /* This is a sanity check */ 52 /* This is a sanity check */
52 TRACE_DEBUG(NONE, "BUG: Unset value in Origin-State-Id in DWR / DWA"); 53 TRACE_DEBUG(NONE, "BUG: Unset value in Origin-State-Id in DWR / DWA");
53 fd_msg_dump_one(NONE, osi); 54 fd_msg_dump_one(NONE, osi);
54 ASSERT(0); /* To check if this really happens, and understand why... */ 55 ASSERT(0); /* To check if this really happens, and understand why... */
55 } 56 }
56 57
57 if (peer->p_hdr.info.runtime.pir_orstate != hdr->avp_value->u32) { 58 if (peer->p_hdr.info.runtime.pir_orstate != hdr->avp_value->u32) {
58 fd_log_debug("Received a new Origin-State-Id from peer %s! (%x / %x)\n", 59 TRACE_DEBUG(INFO, "Received a new Origin-State-Id from peer '%s'! (%x -> %x); resetting the connection.\n",
59 peer->p_hdr.info.pi_diamid, 60 peer->p_hdr.info.pi_diamid,
60 hdr->avp_value->u32, 61 peer->p_hdr.info.runtime.pir_orstate,
61 peer->p_hdr.info.runtime.pir_orstate ); 62 hdr->avp_value->u32 );
63 return EINVAL;
62 } 64 }
63 } 65 }
66 return 0;
64 } 67 }
65 68
66 /* Create and send a DWR */ 69 /* Create and send a DWR */
67 static int send_DWR(struct fd_peer * peer) 70 static int send_DWR(struct fd_peer * peer)
68 { 71 {
89 int reset_tmr = 0; 92 int reset_tmr = 0;
90 93
91 TRACE_ENTRY("%p %d %p", msg, req, peer); 94 TRACE_ENTRY("%p %d %p", msg, req, peer);
92 95
93 /* Check the value of OSI for information */ 96 /* Check the value of OSI for information */
94 check_state_id(*msg, peer); 97 CHECK_FCT( check_state_id(*msg, peer) );
95 98
96 if (req) { 99 if (req) {
97 /* If we receive a DWR, send back a DWA */ 100 /* If we receive a DWR, send back a DWA */
98 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) ); 101 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
99 CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) ); 102 CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) );
100 CHECK_FCT( fd_msg_add_origin ( *msg, 1 ) ); 103 CHECK_FCT( fd_msg_add_origin ( *msg, 1 ) );
101 CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer, FD_CNX_ORDERED) ); 104 CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer, FD_CNX_ORDERED) );
102 105
103 } else { 106 } else {
104 /* Just discard the DWA */ 107 /* Discard the DWA */
105 CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ ); 108 CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ );
106 *msg = NULL; 109 *msg = NULL;
107 110
108 /* And clear the pending DW flag */ 111 /* And clear the pending DW flag */
109 peer->p_flags.pf_dw_pending = 0; 112 peer->p_flags.pf_dw_pending = 0;
120 if (reset_tmr) { 123 if (reset_tmr) {
121 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw); 124 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw);
122 } 125 }
123 126
124 /* If we are in REOPEN state, increment the counter */ 127 /* If we are in REOPEN state, increment the counter */
125 fd_cpu_flush_cache(); 128 if (fd_peer_getstate(peer) == STATE_REOPEN) {
126 if (peer->p_hdr.info.runtime.pir_state == STATE_REOPEN) {
127 peer->p_flags.pf_reopen_cnt += 1; 129 peer->p_flags.pf_reopen_cnt += 1;
128 130
129 if (peer->p_flags.pf_reopen_cnt) { 131 if (peer->p_flags.pf_reopen_cnt) {
130 /* Send a new DWR */ 132 /* Send a new DWR */
131 CHECK_FCT( send_DWR(peer) ); 133 CHECK_FCT( send_DWR(peer) );
"Welcome to our mercurial repository"