Navigation


source: freeDiameter/libfdcore/p_dw.c @ 706:4ffbc9f1e922

Last change on this file since 706:4ffbc9f1e922 was 706:4ffbc9f1e922, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 11 years ago

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.
File size: 6.0 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2011, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36#include "fdcore-internal.h"
37
38/* This file contains code to handle Device Watchdog messages (DWR and DWA) */
39
40/* Check the value of Origin-State-Id is consistent in a DWR or DWA -- we return an error otherwise */
41static int check_state_id(struct msg * msg, struct fd_peer * peer)
42{
43        struct avp * osi;
44       
45        /* Check if the request contains the Origin-State-Id */
46        CHECK_FCT( fd_msg_search_avp ( msg, fd_dict_avp_OSI, &osi ) );
47        if (osi) {
48                /* Check the value is consistent with the saved one */
49                struct avp_hdr * hdr;
50                CHECK_FCT(  fd_msg_avp_hdr( osi, &hdr )  );
51                if (hdr->avp_value == NULL) {
52                        /* This is a sanity check */
53                        TRACE_DEBUG(NONE, "BUG: Unset value in Origin-State-Id in DWR / DWA");
54                        fd_msg_dump_one(NONE, osi);
55                        ASSERT(0); /* To check if this really happens, and understand why... */
56                }
57
58                if (peer->p_hdr.info.runtime.pir_orstate != hdr->avp_value->u32) {
59                        TRACE_DEBUG(INFO, "Received a new Origin-State-Id from peer '%s'! (%x -> %x); resetting the connection.\n", 
60                                peer->p_hdr.info.pi_diamid, 
61                                peer->p_hdr.info.runtime.pir_orstate,
62                                hdr->avp_value->u32 );
63                        return EINVAL;
64                }
65        }
66        return 0;
67}
68
69/* Create and send a DWR */
70static int send_DWR(struct fd_peer * peer)
71{
72        struct msg * msg = NULL;
73       
74        /* Create a new DWR instance */
75        CHECK_FCT( fd_msg_new ( fd_dict_cmd_DWR, MSGFL_ALLOC_ETEID, &msg ) );
76       
77        /* Add the content of the message (only the origin) */
78        CHECK_FCT( fd_msg_add_origin ( msg, 1 ) );
79       
80        /* Now send this message */
81        CHECK_FCT( fd_out_send(&msg, NULL, peer, FD_CNX_ORDERED) );
82       
83        /* And mark the pending DW */
84        peer->p_flags.pf_dw_pending = 1;
85       
86        return 0;
87}
88
89/* Handle an incoming message */
90int fd_p_dw_handle(struct msg ** msg, int req, struct fd_peer * peer)
91{
92        int reset_tmr = 0;
93       
94        TRACE_ENTRY("%p %d %p", msg, req, peer);
95       
96        /* Check the value of OSI for information */
97        CHECK_FCT( check_state_id(*msg, peer) );
98       
99        if (req) {
100                /* If we receive a DWR, send back a DWA */
101                CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
102                CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) );
103                CHECK_FCT( fd_msg_add_origin ( *msg, 1 ) );
104                CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer, FD_CNX_ORDERED) );
105               
106        } else {
107                /* Discard the DWA */
108                CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ );
109                *msg = NULL;
110               
111                /* And clear the pending DW flag */
112                peer->p_flags.pf_dw_pending = 0;
113        }
114       
115        /* Now update timeout */
116        if (req) {
117                /* Update timeout only if we did not already send a DWR ourselves */
118                reset_tmr = !peer->p_flags.pf_dw_pending;
119        } else {
120                /* Reset the timer */
121                reset_tmr = 1;
122        }
123        if (reset_tmr) {
124                fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw);
125        }
126       
127        /* If we are in REOPEN state, increment the counter */
128        if (fd_peer_getstate(peer) == STATE_REOPEN) {
129                peer->p_flags.pf_reopen_cnt += 1;
130               
131                if (peer->p_flags.pf_reopen_cnt) {
132                        /* Send a new DWR */
133                        CHECK_FCT( send_DWR(peer) );
134                } else {
135                        /* Move to OPEN state */
136                        CHECK_FCT( fd_psm_change_state(peer, STATE_OPEN) );
137                }
138        }
139               
140        return 0;
141}
142
143/* Handle a timeout in the PSM (OPEN or REOPEN state only) */
144int fd_p_dw_timeout(struct fd_peer * peer)
145{
146        TRACE_ENTRY("%p", peer);
147
148        if (peer->p_flags.pf_dw_pending) {
149                /* We have sent a DWR and received no answer during TwTimer */
150                CHECK_FCT( fd_psm_change_state(peer, STATE_SUSPECT) );
151                fd_psm_next_timeout(peer, 0, 2 * (peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw) );
152        } else {
153                /* The timeout has expired, send a DWR */
154                CHECK_FCT( send_DWR(peer) );
155                fd_psm_next_timeout(peer, 0, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw );
156        }
157       
158        return 0;
159}
160
161/* Handle DW exchanges after the peer has come alive again */
162int fd_p_dw_reopen(struct fd_peer * peer)
163{
164        TRACE_ENTRY("%p", peer);
165
166        peer->p_flags.pf_reopen_cnt = 1;
167        peer->p_flags.pf_cnx_pb = 0;
168        CHECK_FCT( send_DWR(peer) );
169       
170        return 0;
171}
172
173
Note: See TracBrowser for help on using the repository browser.