Mercurial > hg > freeDiameter
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) ); |