Files
m241Neelima/components/ip_net2-6.9/ipdiameter/src/ipdiameter_peer_fsm.c
T
2026-07-30 11:19:44 +05:30

886 lines
32 KiB
C

/* ipdiameter_peer_fsm.c - IPNet Diameter peer FSM file */
/*
* Copyright (c) 2007 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement. No license to Wind River intellectual property rights
* is granted herein. All rights not licensed by Wind River are reserved
* by Wind River.
*/
/*
modification history
--------------------
01e,03feb09,tlu Remove R_RCV_CEA and I_RCV_CER events from peer FSM
01d,05apr08,ggz Modifications for non blocking TCP connection with peers
01c,05sep07,tlu Fix checking of the return code from processing CER
01b,05jul07,tlu Replace ipcom_printf by IPCOM_LOG
01a,03may07,tlu Created.
*/
/*
****************************************************************************
* INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_sock.h>
#include <ipcom_os.h>
#include <ipcom_syslog.h>
#include <ipcom_err.h>
#include <ipcom_clib.h>
#include <ipcom_ipd.h>
#include <ipnet_h.h>
#include "ipdiameter.h"
/*
****************************************************************************
* EXTERN PROTOTYPES
****************************************************************************
*/
IP_EXTERN Ipdiameter_data ipdiameter;
/*
****************************************************************************
* DEFINES
****************************************************************************
*/
/* This is a compile flag, turning on it will build debug message into image */
#undef DIAMETER_DEBUG
/*
****************************************************************************
* LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* DATA
****************************************************************************
*/
/*
****************************************************************************
* PUBLIC FUNCTIONS
****************************************************************************
* Refer to RFC 3588, section 5.6
*/
IP_PUBLIC Ip_err
ipdiameter_peer_fsm(Ipdiameter_peer_entry *peer, struct Ipdiameter_header *hdr, int event)
{
Ip_err retval = IPCOM_SUCCESS;
Ipdiameter_header *hdr_v = (Ipdiameter_header *)hdr;
Ip_bool win_elect;
Ip_u32 result_code = DIAMETER_SUCCESS;
Ip_fd fd = IP_INVALID_SOCKET, fd6 = IP_INVALID_SOCKET;
#ifdef DIAMETER_DEBUG
ipcom_printf("Calling ipdiameter_peer_fsm, state %s, event %d\n",
ipdiameter_peer_state(peer->state), event);
#endif
if (peer == IP_NULL) {
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, pass in a NULL peer\n");
return IPCOM_ERR_INVALID_ARG;
}
switch (peer->state)
{
case DIAMETER_PEER_STATE_CLOSED:
switch (event) {
case DIAMETER_PEER_EV_START:
if (ipdiameter.node_type == DIAMETER_PEER_PROXY_AGENT)
{
/* initiate non-blocking connection */
retval = ipdiameter_peer_init_conn_req(peer);
/* Warning: this state of peer is used in non blocking select processing */
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_CONN_ACK);
/* The socket is in non blocing mode but the connection might
have already been established. If yes then continue procesiing here.
Otherwise the connection will be processed in select function after
the socket reply */
if ((retval != IPCOM_SUCCESS) && (retval != IP_ERRNO_EINPROGRESS))
{
ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_I_RCV_CONN_NACK);
retval = IPCOM_ERR_FAILED;
}
else if (retval == IP_ERRNO_EINPROGRESS)
{
/* IP_ERRNO_EINPROGRESS - leave the peers state in
DIAMETER_PEER_STATE_WAIT_CONN_ACK. The connection will be handled
when the socket replyes */
retval = IPCOM_SUCCESS;
}
else /* Success */
{
/* Immidiate socket connection has been established. Run the peer FSM */
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_I_RCV_CONN_ACK);
}
}
else
{
/* initiate connect request */
retval = ipdiameter_peer_init_conn_req(peer);
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_CONN_ACK);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to send out the packet\n");
ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_I_RCV_CONN_NACK);
retval = IPCOM_ERR_FAILED;
} else {
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_I_RCV_CONN_ACK);
}
}
break;
case DIAMETER_PEER_EV_R_CONN_CER:
case DIAMETER_PEER_EV_R_RCV_CER:
#ifdef IPCOM_USE_INET
fd = peer->fd;
#endif
#ifdef IPCOM_USE_INET6
fd6 = peer->fd6;
#endif
if (fd == IP_INVALID_SOCKET && fd6 == IP_INVALID_SOCKET)
/* peer is not connected, remains in CLOSED state */
break;
if (!peer->initiator)
{
#ifdef DIAMETER_DEBUG
ipcom_printf("ipdiameter_peer_fsm: respond to accept the connect\n");
#endif
/* respond to accept the connection */
retval = ipdiameter_peer_resp_accept(peer);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to accept the connect\n");
goto error;
}
}
/* process the CER */
result_code = ipdiameter_peer_process_CER(peer, hdr);
if (!peer->initiator)
{
/* cancel the recon timer */
(void)ipcom_tmo2_cancel(&peer->reconn_tmo);
/* respond to send the CEA */
retval = ipdiameter_send_CEA(peer, hdr_v, result_code);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to send out the CEA packet\n");
goto error;
}
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_R_OPEN);
/* check whether there is pending package to transmit */
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_SEND_MESSAGE);
break;
default:
break;
}
break;
case DIAMETER_PEER_STATE_WAIT_CONN_ACK:
switch (event) {
case DIAMETER_PEER_EV_I_RCV_CONN_ACK:
if (peer->initiator)
{
/* send the CER */
retval = ipdiameter_send_CER(peer);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to send out the CEA packet\n");
goto error;
}
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_I_CEA);
break;
case DIAMETER_PEER_EV_I_RCV_CONN_NACK:
/* clean up */
retval = ipdiameter_peer_cleanup(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed in peer cleanup\n");
break;
case DIAMETER_PEER_EV_R_CONN_CER:
if (!peer->initiator)
{
/* respond to accept the connection */
retval = ipdiameter_peer_resp_accept(peer);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to accept the connect\n");
goto error;
}
}
/* process the CER */
retval = ipdiameter_peer_process_CER(peer, hdr);
if (retval != DIAMETER_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to process the CER\n");
goto error;
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_CONN_ACK_ELECT);
break;
case DIAMETER_PEER_EV_TIMEOUT:
/* process the error */
retval = ipdiameter_peer_error(peer);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed in peer error handling\n");
}
break;
default:
break;
}
break;
case DIAMETER_PEER_STATE_WAIT_I_CEA:
switch (event) {
case DIAMETER_PEER_EV_I_RCV_CEA:
/* process the CEA */
retval = ipdiameter_peer_process_CEA(peer, hdr);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed to process the CEA\n");
goto error;
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_I_OPEN);
/* check whether there is pending package to transmit */
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_SEND_MESSAGE);
break;
case DIAMETER_PEER_EV_R_CONN_CER:
if (!peer->initiator)
{
/* respond to accept the connection */
retval = ipdiameter_peer_resp_accept(peer);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to accept the connect\n");
goto error;
}
}
/* process the CER */
retval = ipdiameter_peer_process_CER(peer, hdr);
if (retval != DIAMETER_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to process the CER\n");
goto error;
}
/* perform the peer election */
win_elect = ipdiameter_peer_elect(peer);
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_RETURNS);
if (win_elect)
{
retval = ipdiameter_peer_fsm(peer, hdr, DIAMETER_PEER_EV_WIN_ELECTION);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed in peer FSM with EV_WIN_ELECTION\n");
}
break;
case DIAMETER_PEER_EV_I_PEER_DISC:
if (peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
break;
case DIAMETER_PEER_EV_I_RCV_NON_CEA:
/* process the error */
retval = ipdiameter_peer_error(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed in peer error handling\n");
break;
case DIAMETER_PEER_EV_TIMEOUT:
/* process the error */
retval = ipdiameter_peer_error(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed in peer error handling\n");
break;
default:
break;
}
break;
case DIAMETER_PEER_STATE_WAIT_CONN_ACK_ELECT:
switch (event) {
case DIAMETER_PEER_EV_I_RCV_CONN_ACK:
if (peer->initiator)
{
/* send the CER */
retval = ipdiameter_send_CER(peer);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to send out the CEA packet\n");
goto error;
}
}
/* perform the peer election */
win_elect = ipdiameter_peer_elect(peer);
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_RETURNS);
if (win_elect)
{
retval = ipdiameter_peer_fsm(peer, hdr, DIAMETER_PEER_EV_WIN_ELECTION);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed in peer FSM with EV_WIN_ELECTION\n");
}
break;
case DIAMETER_PEER_EV_I_RCV_CONN_NACK:
if (!peer->initiator)
{
/* cancel the recon timer */
(void)ipcom_tmo2_cancel(&peer->reconn_tmo);
/* send the CEA */
retval = ipdiameter_send_CEA(peer, hdr_v, DIAMETER_SUCCESS);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to send out the CEA packet\n");
goto error;
}
}
/* Change the state to open */
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_R_OPEN);
/* check whether there is pending package to transmit */
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_SEND_MESSAGE);
break;
case DIAMETER_PEER_EV_R_PEER_DISC:
if (!peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_CONN_ACK);
break;
case DIAMETER_PEER_EV_R_CONN_CER:
if (!peer->initiator)
{
/* Reject the peer */
retval = ipdiameter_peer_reject(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to reject the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_CONN_ACK_ELECT);
break;
case DIAMETER_PEER_EV_TIMEOUT:
/* process the error */
retval = ipdiameter_peer_error(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed in peer error handling\n");
break;
default:
break;
}
break;
case DIAMETER_PEER_STATE_WAIT_RETURNS:
switch (event) {
case DIAMETER_PEER_EV_WIN_ELECTION:
if (peer->initiator)
{
/* Disconnect the peer if the local host is the winner */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
else
{
/* cancel the recon timer */
(void)ipcom_tmo2_cancel(&peer->reconn_tmo);
/* Send the CEA */
retval = ipdiameter_send_CEA(peer, hdr_v, DIAMETER_SUCCESS);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to send out the CEA packet\n");
goto error;
}
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_R_OPEN);
/* check whether there is pending package to transmit */
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_SEND_MESSAGE);
break;
case DIAMETER_PEER_EV_I_PEER_DISC:
if (peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
else
{
/* cancel the recon timer */
(void)ipcom_tmo2_cancel(&peer->reconn_tmo);
/* Send the CEA */
retval = ipdiameter_send_CEA(peer, hdr_v, DIAMETER_SUCCESS);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to send out the CEA packet\n");
goto error;
}
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_R_OPEN);
/* check whether there is pending package to transmit */
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_SEND_MESSAGE);
break;
case DIAMETER_PEER_EV_I_RCV_CEA:
if (!peer->initiator)
{
/* cancel the recon timer */
(void)ipcom_tmo2_cancel(&peer->reconn_tmo);
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_I_OPEN);
/* check whether there is pending package to transmit */
retval = ipdiameter_peer_fsm(peer, IP_NULL, DIAMETER_PEER_EV_SEND_MESSAGE);
break;
case DIAMETER_PEER_EV_R_PEER_DISC:
if (!peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_I_CEA);
break;
case DIAMETER_PEER_EV_R_CONN_CER:
if (!peer->initiator)
{
/* Reject the peer */
retval = ipdiameter_peer_reject(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to reject the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_WAIT_RETURNS);
break;
case DIAMETER_PEER_EV_TIMEOUT:
/* process the error */
retval = ipdiameter_peer_error(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed in peer error handling\n");
break;
default:
break;
}
break;
case DIAMETER_PEER_STATE_R_OPEN:
switch (event) {
case DIAMETER_PEER_EV_SEND_MESSAGE:
if (peer->initiator)
{
/* send out the messge */
retval = ipdiameter_peer_send_msg(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm: failed to send out the message\n");
}
/* the peer remains R-Open state */
break;
case DIAMETER_PEER_EV_R_RCV_MESSAGE:
/* process the messge */
retval = ipdiameter_peer_process_msg(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm: failed to process the message\n");
/* the peer remains R-Open state */
break;
case DIAMETER_PEER_EV_R_RCV_DWR:
/* process the DWR messge */
result_code = ipdiameter_peer_process_DWR(peer, hdr);
if (!peer->initiator)
{
/* send out the DWA messge */
retval = ipdiameter_send_DWA(peer, hdr_v, result_code);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed to send out the DWA message\n");
goto error;
}
}
/* the peer remains R-Open state */
break;
case DIAMETER_PEER_EV_R_RCV_DWA:
/* process the DWA messge */
retval = ipdiameter_peer_process_DWA(peer, hdr);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed to process the DWA\n");
goto error;
}
/* the peer remains R-Open state */
break;
case DIAMETER_PEER_EV_R_CONN_CER:
if (!peer->initiator)
{
/* Reject the peer */
retval = ipdiameter_peer_reject(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to reject the peer\n");
}
/* the peer remains R-Open state */
break;
case DIAMETER_PEER_EV_STOP:
if (!peer->initiator)
{
/* start reconn timer */
retval = ipdiameter_peer_start_reconn_timer(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to start reconn timer\n");
/* send out the DPR */
retval = ipdiameter_send_DPR(peer, DIAMETER_PEER_DO_NOT_WANT_TO_TALK_TO_YOU);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to send out the DPR message\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSING);
break;
case DIAMETER_PEER_EV_R_RCV_DPR:
if (!peer->initiator)
{
/* send out the DPA */
retval = ipdiameter_send_DPA(peer, hdr_v, DIAMETER_SUCCESS);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to send out the DPA message\n");
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
case DIAMETER_PEER_EV_R_PEER_DISC:
if (!peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
default:
break;
}
break;
case DIAMETER_PEER_STATE_I_OPEN:
switch (event) {
case DIAMETER_PEER_EV_SEND_MESSAGE:
if (peer->initiator)
{
/* send out the messge */
retval = ipdiameter_peer_send_msg(peer);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm, failed to send out the CEA packet\n");
goto error;
}
}
/* the session remains I-Open state */
break;
case DIAMETER_PEER_EV_I_RCV_MESSAGE:
/* process the messge */
retval = ipdiameter_peer_process_msg(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm: failed to process the message\n");
/* the session remains I-Open state */
break;
case DIAMETER_PEER_EV_I_RCV_DWR:
/* process the DWR messge */
result_code = ipdiameter_peer_process_DWR(peer, hdr);
if (peer->initiator)
{
/* send out the DWA messge */
retval = ipdiameter_send_DWA(peer, hdr_v, result_code);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed to send out the DWA message\n");
goto error;
}
}
/* the session remains I-Open state */
break;
case DIAMETER_PEER_EV_I_RCV_DWA:
/* process the DWA messge */
retval = ipdiameter_peer_process_DWA(peer, hdr);
if (retval != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed to process the DWA\n");
goto error;
}
/* the session remains I-Open state */
break;
case DIAMETER_PEER_EV_R_CONN_CER:
if (!peer->initiator)
{
/* Reject the peer */
retval = ipdiameter_peer_reject(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to reject the peer\n");
}
/* the session remains I-Open state */
break;
case DIAMETER_PEER_EV_STOP:
if (peer->initiator)
{
/* start reconn timer */
retval = ipdiameter_peer_start_reconn_timer(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to start reconn timer\n");
/* send out the DPR */
retval = ipdiameter_send_DPR(peer, DIAMETER_PEER_DO_NOT_WANT_TO_TALK_TO_YOU);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to send out the DPR message\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSING);
break;
case DIAMETER_PEER_EV_I_RCV_DPR:
if (peer->initiator)
{
/* send out the DPA */
retval = ipdiameter_send_DPA(peer, hdr_v, DIAMETER_SUCCESS);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to send out the DPA message\n");
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
case DIAMETER_PEER_EV_I_PEER_DISC:
if (peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
default:
break;
}
break;
case DIAMETER_PEER_STATE_CLOSING:
switch (event) {
case DIAMETER_PEER_EV_I_RCV_DPA:
if (peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
case DIAMETER_PEER_EV_R_RCV_DPA:
if (!peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
case DIAMETER_PEER_EV_TIMEOUT:
/* process the error */
retval = ipdiameter_peer_error(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "ipdiameter_peer_fsm: failed in peer error handling\n");
break;
case DIAMETER_PEER_EV_I_PEER_DISC:
if (peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
case DIAMETER_PEER_EV_R_PEER_DISC:
if (!peer->initiator)
{
/* Disconnect the peer */
retval = ipdiameter_peer_disc(peer);
if (retval != IPCOM_SUCCESS)
IPCOM_LOG0(WARNING, "ipdiameter_peer_fsm, failed to disconnect the peer\n");
}
ipdiameter_peer_set_state(peer, DIAMETER_PEER_STATE_CLOSED);
break;
default:
break;
}
break;
default:
break;
}
#ifdef DIAMETER_DEBUG
ipcom_printf("ipdiameter_peer_fsm successful\n");
ipdiameter_print_peer(peer);
#endif
return retval;
error:
(void)ipdiameter_peer_disc(peer);
#ifdef DIAMETER_DEBUG
ipcom_printf("ipdiameter_peer_fsm failed\n");
ipdiameter_print_peer(peer);
#endif
return retval;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/