Commit 292243c1 authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Backup

parent ae0991fe
......@@ -20,6 +20,8 @@ SET(FD_COMMON_SRC
queues.c
peers.c
p_ce.c
p_dw.c
p_dp.c
p_expiry.c
p_out.c
p_psm.c
......
......@@ -231,6 +231,9 @@ int fd_psm_start();
int fd_psm_begin(struct fd_peer * peer );
int fd_psm_terminate(struct fd_peer * peer );
void fd_psm_abord(struct fd_peer * peer );
void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay);
int fd_psm_change_state(struct fd_peer * peer, int new_state);
void fd_psm_cleanup(struct fd_peer * peer);
/* Peer out */
int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer);
......@@ -242,8 +245,13 @@ int fd_p_sr_store(struct sr_list * srlist, struct msg **req, uint32_t *hbhloc);
int fd_p_sr_fetch(struct sr_list * srlist, uint32_t hbh, struct msg **req);
void fd_p_sr_failover(struct sr_list * srlist);
/* Capabilities Exchange */
int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer);
/* Local Link messages (CER/CEA, DWR/DWA, DPR/DPA) */
int fd_p_ce_handle(struct msg ** msg, struct fd_peer * peer);
int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid);
int fd_p_dw_handle(struct msg ** msg, struct fd_peer * peer);
int fd_p_dw_timeout(struct fd_peer * peer);
int fd_p_dp_handle(struct msg ** msg, struct fd_peer * peer);
int fd_p_dp_initiate(struct fd_peer * peer);
/* Active peers -- routing process should only ever take the read lock, the write lock is managed by PSMs */
extern struct fd_list fd_g_activ_peers;
......
......@@ -317,6 +317,7 @@ connpeer: {
memset(&fddpi, 0, sizeof(fddpi));
fd_list_init( &fddpi.pi_endpoints, NULL );
fd_list_init( &fddpi.pi_apps, NULL );
fddpi.pi_flags.persist = PI_PRST_ALWAYS;
}
CONNPEER '=' QSTRING peerinfo ';'
{
......
......@@ -37,9 +37,33 @@
/* This file contains code to handle Capabilities Exchange messages (CER and CEA) */
int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer)
int fd_p_ce_handle(struct msg ** msg, struct fd_peer * peer)
{
/* Save all information from the CER into the peer structure, after cleaning old information if any */
TODO("Handle depending on CER or CEA and peer state");
return ENOTSUP;
}
int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid)
{
switch (peer->p_hdr.info.pi_state) {
case STATE_CLOSED:
TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
/* In case of error : DIAMETER_UNKNOWN_PEER */
break;
case STATE_WAITCNXACK:
case STATE_WAITCEA:
TODO("Election");
break;
default:
TODO("Reply with error CEA");
TODO("Close the connection");
/* reject_incoming_connection */
}
return ENOTSUP;
}
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2009, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
#include "fD.h"
/* This file contains code to handle Disconnect Peer messages (DPR and DPA) */
/* Handle a received message */
int fd_p_dp_handle(struct msg ** msg, struct fd_peer * peer)
{
TODO("Handle depending on DPR or DPA and peer state");
return ENOTSUP;
}
/* Start disconnection of a peer: send DPR */
int fd_p_dp_initiate(struct fd_peer * peer)
{
TODO("Create the DPR message");
TODO("Send it");
TODO("Mark the peer as CLOSING");
TODO("Reset the timer");
return ENOTSUP;
}
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2009, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
#include "fD.h"
/* This file contains code to handle Device Watchdog messages (DWR and DWA) */
/* Handle an incoming message */
int fd_p_dw_handle(struct msg ** msg, struct fd_peer * peer)
{
TODO("Handle depending on DWR or DWA and peer state");
return ENOTSUP;
}
/* Handle a timeout in the PSM : send DWR, fail the peer, manage reopen state */
int fd_p_dw_timeout(struct fd_peer * peer)
{
TODO("...");
return ENOTSUP;
}
......@@ -35,8 +35,8 @@
#include "fD.h"
/* Delay for garbage collection of expired threads, in seconds */
#define GC_TIME 60
/* Delay for garbage collection of expired peers, in seconds */
#define GC_TIME 120
static pthread_t exp_thr;
static pthread_t gc_thr;
......@@ -63,8 +63,8 @@ static void * gc_th_fct(void * arg)
if (peer->p_hdr.info.pi_state != STATE_ZOMBIE)
continue;
if (peer->p_hdr.info.pi_flags.exp == PI_EXP_NONE)
continue; /* This peer was not supposed to expire, keep it in the list */
if (peer->p_hdr.info.pi_flags.persist == PI_PRST_ALWAYS)
continue; /* This peer was not supposed to terminate, keep it in the list for debug */
/* Ok, the peer was expired, let's remove it */
li = li->prev; /* to avoid breaking the loop */
......
......@@ -145,7 +145,7 @@ static int leave_open_state(struct fd_peer * peer)
/* Helpers for state changes */
/************************************************************************/
/* Change state */
static int change_state(struct fd_peer * peer, int new_state)
int fd_psm_change_state(struct fd_peer * peer, int new_state)
{
int old;
......@@ -170,11 +170,15 @@ static int change_state(struct fd_peer * peer, int new_state)
CHECK_FCT( enter_open_state(peer) );
}
if ((new_state == STATE_CLOSED) && (peer->p_hdr.info.pi_flags.persist == PI_PRST_NONE)) {
CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) );
}
return 0;
}
/* Set timeout timer of next event */
static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
{
/* Initialize the timer */
CHECK_POSIX_DO( clock_gettime( CLOCK_REALTIME, &peer->p_psm_timer ), ASSERT(0) );
......@@ -202,12 +206,29 @@ static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
#endif
}
/* Cleanup the peer */
void fd_psm_cleanup(struct fd_peer * peer)
{
/* Move to CLOSED state */
CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ );
/* Destroy the connection */
if (peer->p_cnxctx) {
fd_cnx_destroy(peer->p_cnxctx);
peer->p_cnxctx = NULL;
}
/* What else ? */
TODO("...");
}
/************************************************************************/
/* The PSM thread */
/************************************************************************/
/* Cancelation cleanup : set ZOMBIE state in the peer */
void cleanup_state(void * arg)
void cleanup_setstate(void * arg)
{
struct fd_peer * peer = (struct fd_peer *)arg;
CHECK_PARAMS_DO( CHECK_PEER(peer), return );
......@@ -226,7 +247,7 @@ static void * p_psm_th( void * arg )
CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) );
pthread_cleanup_push( cleanup_state, arg );
pthread_cleanup_push( cleanup_setstate, arg );
/* Set the thread name */
{
......@@ -243,9 +264,9 @@ static void * p_psm_th( void * arg )
/* Initialize the timer */
if (peer->p_flags.pf_responder) {
psm_next_timeout(peer, 0, INCNX_TIMEOUT);
fd_psm_next_timeout(peer, 0, INCNX_TIMEOUT);
} else {
psm_next_timeout(peer, created_started, 0);
fd_psm_next_timeout(peer, created_started, 0);
}
psm_loop:
......@@ -278,22 +299,23 @@ psm_loop:
/* Requests to terminate the peer object */
if (event == FDEVP_TERMINATE) {
switch (peer->p_hdr.info.pi_state) {
case STATE_OPEN:
case STATE_REOPEN:
/* We cannot just close the conenction, we have to send a DPR first */
CHECK_FCT_DO( fd_p_dp_initiate(peer), goto psm_end );
goto psm_loop;
/*
case STATE_CLOSING:
case STATE_WAITCNXACK:
case STATE_WAITCNXACK_ELEC:
case STATE_WAITCEA:
case STATE_SUSPECT:
/* In these cases, we just cleanup the peer object and terminate now */
TODO("Cleanup the PSM: terminate connection object, ...");
case STATE_CLOSED:
/* Then we just terminate the PSM */
*/
default:
/* In these cases, we just cleanup the peer object (if needed) and terminate */
goto psm_end;
case STATE_OPEN:
case STATE_REOPEN:
/* We cannot just close the conenction, we have to send a DPR first */
TODO("Send DPR, mark the peer as CLOSING");
goto psm_loop;
}
}
......@@ -310,8 +332,8 @@ psm_loop:
goto psm_loop;
} );
TRACE_DEBUG(FULL, "Received this message from '%s':", peer->p_hdr.info.pi_diamid);
fd_msg_dump_walk(FULL, msg);
TRACE_DEBUG(FULL, "Received a message (%zdb) from '%s'", ev_sz, peer->p_hdr.info.pi_diamid);
fd_msg_dump_walk(FULL + 1, msg);
/* Extract the header */
CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end );
......@@ -332,9 +354,6 @@ psm_loop:
CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end );
}
/* We received a valid message, update the expiry timer */
CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end );
/* Now handle non-link-local messages */
if (fd_msg_is_routable(msg)) {
/* If we are not in OPEN state, discard the message */
......@@ -343,6 +362,9 @@ psm_loop:
fd_msg_dump_walk(NONE, msg);
fd_msg_free(msg);
} else {
/* We received a valid message, update the expiry timer */
CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end );
/* Set the message source and add the Route-Record */
CHECK_FCT_DO( fd_msg_source_set( msg, peer->p_hdr.info.pi_diamid, 1, fd_g_config->cnf_dict ), goto psm_end);
......@@ -351,7 +373,7 @@ psm_loop:
/* Update the peer timer */
if (!peer->p_flags.pf_dw_pending) {
psm_next_timeout(peer, 1, peer->p_hdr.info.pi_twtimer ?: fd_g_config->cnf_timer_tw);
fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_twtimer ?: fd_g_config->cnf_timer_tw);
}
}
goto psm_loop;
......@@ -373,16 +395,53 @@ psm_loop:
} );
}
ASSERT( hdr->msg_appl == 0 ); /* buggy fd_msg_is_routable() ? */
/* Handle the LL message and update the expiry timer appropriately */
TODO("...");
switch (hdr->msg_code) {
case CC_DEVICE_WATCHDOG:
CHECK_FCT_DO( fd_p_dw_handle(&msg, peer), goto psm_end );
break;
case CC_DISCONNECT_PEER:
CHECK_FCT_DO( fd_p_dp_handle(&msg, peer), goto psm_end );
break;
case CC_CAPABILITIES_EXCHANGE:
CHECK_FCT_DO( fd_p_ce_handle(&msg, peer), goto psm_end );
break;
default:
/* Unknown / unexpected / invalid message */
TODO("Log, return error message if request");
};
/* At this point the message must have been fully handled already */
if (msg) {
fd_log_debug("Internal error: unhandled message (discarded)!\n");
fd_msg_dump_walk(NONE, msg);
fd_msg_free(msg);
}
goto psm_loop;
}
/* The connection object is broken */
if (event == FDEVP_CNX_ERROR) {
TODO("Destroy the connection object");
TODO("Mark the error in the peer (pf_cnx_pb)");
TODO("Move to closed state, Requeue all messages to a different connection (failover)");
TODO("If pi_flags.exp, terminate the peer");
/* Cleanup the peer */
fd_psm_cleanup(peer);
/* Mark the connection problem */
peer->p_flags.pf_cnx_pb = 1;
/* Move to CLOSED */
CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end );
/* Reset the timer */
fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc);
/* Loop */
goto psm_loop;
}
/* The connection notified a change in endpoints */
......@@ -408,30 +467,20 @@ psm_loop:
struct cnx_incoming * params = ev_data;
ASSERT(params);
switch (peer->p_hdr.info.pi_state) {
case STATE_CLOSED:
TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
/* In case of error : DIAMETER_UNKNOWN_PEER */
CHECK_FCT_DO( fd_p_ce_merge(peer, params->cer),
{
} );
break;
case STATE_WAITCNXACK:
case STATE_WAITCEA:
TODO("Election");
break;
default:
TODO("Reply with error CEA");
TODO("Close the connection");
/* reject_incoming_connection */
/* Handle the message */
CHECK_FCT_DO( fd_p_ce_handle_newCER(&params->cer, peer, &params->cnx, params->validate), goto psm_end );
/* Cleanup if needed */
if (params->cnx) {
fd_cnx_destroy(params->cnx);
params->cnx = NULL;
}
if (params->cer) {
CHECK_FCT_DO( fd_msg_free(params->cer), );
params->cer = NULL;
}
/* Loop */
free(ev_data);
goto psm_loop;
}
......@@ -439,8 +488,28 @@ psm_loop:
/* The timeout for the current state has been reached */
if (event == FDEVP_PSM_TIMEOUT) {
switch (peer->p_hdr.info.pi_state) {
case STATE_OPEN:
case STATE_REOPEN:
CHECK_FCT_DO( fd_p_dw_timeout(peer), goto psm_end );
break;
case STATE_CLOSED:
TODO("Initiate a new connection");
break;
case STATE_CLOSING:
case STATE_SUSPECT:
case STATE_WAITCNXACK:
case STATE_WAITCEA:
/* Destroy the connection, restart the timer to a new connection attempt */
fd_psm_cleanup(peer);
fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc);
CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end );
break;
case STATE_WAITCNXACK_ELEC:
TODO("Abort initiating side, handle the receiver side");
break;
}
}
......@@ -448,12 +517,13 @@ psm_loop:
TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event));
if (event == FDEVP_PSM_TIMEOUT) {
/* We have not handled timeout in this state, let's postpone next alert */
psm_next_timeout(peer, 0, 60);
fd_psm_next_timeout(peer, 0, 60);
}
goto psm_loop;
psm_end:
fd_psm_cleanup(peer);
pthread_cleanup_pop(1); /* set STATE_ZOMBIE */
peer->p_psm = (pthread_t)NULL;
pthread_detach(pthread_self());
......
......@@ -101,16 +101,17 @@ int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct pe
CHECK_MALLOC( p->p_hdr.info.pi_realm = strdup(info->pi_realm) );
}
p->p_hdr.info.pi_flags.pro3 = info->pi_flags.pro3;
p->p_hdr.info.pi_flags.pro4 = info->pi_flags.pro4;
p->p_hdr.info.pi_flags.alg = info->pi_flags.alg;
p->p_hdr.info.pi_flags.sec = info->pi_flags.sec;
p->p_hdr.info.pi_flags.exp = info->pi_flags.exp;
p->p_hdr.info.pi_lft = info->pi_lft;
p->p_hdr.info.pi_port = info->pi_port;
p->p_hdr.info.pi_tctimer = info->pi_tctimer;
p->p_hdr.info.pi_twtimer = info->pi_twtimer;
p->p_hdr.info.pi_flags.pro3 = info->pi_flags.pro3;
p->p_hdr.info.pi_flags.pro4 = info->pi_flags.pro4;
p->p_hdr.info.pi_flags.alg = info->pi_flags.alg;
p->p_hdr.info.pi_flags.sec = info->pi_flags.sec;
p->p_hdr.info.pi_flags.exp = info->pi_flags.exp;
p->p_hdr.info.pi_flags.persist = info->pi_flags.persist;
p->p_hdr.info.pi_lft = info->pi_lft;
p->p_hdr.info.pi_port = info->pi_port;
p->p_hdr.info.pi_tctimer = info->pi_tctimer;
p->p_hdr.info.pi_twtimer = info->pi_twtimer;
if (info->pi_sec_data.priority) {
CHECK_MALLOC( p->p_hdr.info.pi_sec_data.priority = strdup(info->pi_sec_data.priority) );
......@@ -441,6 +442,10 @@ int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx )
CHECK_MALLOC_DO( peer->p_dbgorig = strdup(fd_cnx_getid(*cnx)), { ret = ENOMEM; goto out; } );
peer->p_flags.pf_responder = 1;
/* Set this peer to expire on inactivity */
peer->p_hdr.info.pi_flags.exp = PI_EXP_INACTIVE;
peer->p_hdr.info.pi_lft = 3600 * 3; /* 3 hours without any message */
/* Upgrade the lock to write lock */
CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&fd_g_peers_rw), goto out );
......
......@@ -247,7 +247,7 @@ enum peer_state {
We have sent a CER on our initiated connection, and received a CER from the remote peer on another connection. Election.
If we win the election, we must disconnect the initiated connection and send a CEA on the other => we go to OPEN state.
If we lose, we disconnect the other connection (receiver) and fallback to WAITCEA state. */
STATE_OPEN_HANDSHAKE, /* TLS Handshake and validation are in progress in open state */
STATE_OPEN_HANDSHAKE, /* TLS Handshake and validation are in progress in open state -- we show the state because it can last a long time */
/* Failover state machine */
STATE_SUSPECT, /* A DWR was sent and not answered within TwTime. Failover in progress. */
......@@ -306,6 +306,10 @@ struct peer_info {
#define PI_EXP_INACTIVE 1 /* the peer entry expires (i.e. is deleted) after pi_lft seconds without activity */
unsigned exp :1;
#define PI_PRST_NONE 0 /* the peer entry is deleted after disconnection / error */
#define PI_PRST_ALWAYS 1 /* the peer entry is persistant (will be kept as ZOMBIE in case of error) */
unsigned persist :1;
unsigned inband_none :1; /* This is only meaningful with pi_flags.sec == 3 */
unsigned inband_tls :1; /* This is only meaningful with pi_flags.sec == 3 */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment