original files of m241
This commit is contained in:
@@ -0,0 +1,885 @@
|
||||
/* 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
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user