# HG changeset patch # User Sebastien Decugis # Date 1257480336 -32400 # Node ID 7e1deaa89540c4ae3ce2304b635624dbd52bc782 # Parent d7535cf7bab5163893c4c0f8ba1936d6e53fd5ac Some progress on the PSM diff -r d7535cf7bab5 -r 7e1deaa89540 freeDiameter/fD.h --- a/freeDiameter/fD.h Thu Nov 05 18:43:42 2009 +0900 +++ b/freeDiameter/fD.h Fri Nov 06 13:05:36 2009 +0900 @@ -261,11 +261,13 @@ void fd_p_sr_failover(struct sr_list * srlist); /* 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_msgrcv(struct msg ** msg, int req, 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_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator); +int fd_p_ce_winelection(struct fd_peer * peer); +int fd_p_dw_handle(struct msg ** msg, int req, 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_handle(struct msg ** msg, int req, 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 */ diff -r d7535cf7bab5 -r 7e1deaa89540 freeDiameter/p_ce.c --- a/freeDiameter/p_ce.c Thu Nov 05 18:43:42 2009 +0900 +++ b/freeDiameter/p_ce.c Fri Nov 06 13:05:36 2009 +0900 @@ -35,24 +35,86 @@ #include "fD.h" -/* This file contains code to handle Capabilities Exchange messages (CER and CEA) */ +/* This file contains code to handle Capabilities Exchange messages (CER and CEA) and election process */ -int fd_p_ce_handle(struct msg ** msg, struct fd_peer * peer) +/* Save a connection as peer's principal */ +static int set_peer_cnx(struct fd_peer * peer, struct cnxctx **cnx) { - TODO("Handle depending on CER or CEA and peer state"); + TODO("Save *cnx into peer->p_cnxctx"); + TODO("Set fifo of *cnx to peer->p_events"); + TODO("If connection is already TLS, read the credentials"); + TODO("Read the remote endpoints"); return ENOTSUP; } +static int process_valid_CEA(struct fd_peer * peer, struct msg ** cea) +{ + /* Save info from the CEA into the peer */ + + /* Handshake if needed */ + + /* Save credentials if needed */ + + TODO("..."); + return ENOTSUP; + +} + +/* We have received a Capabilities Exchange message on the peer connection */ +int fd_p_ce_msgrcv(struct msg ** msg, int req, struct fd_peer * peer) +{ + TRACE_ENTRY("%p %p", msg, peer); + CHECK_PARAMS( msg && *msg && CHECK_PEER(peer) ); + + /* The only valid situation where we are called is in WAITCEA and we receive a CEA */ + + /* Note : to implement Capabilities Update, we would need to change here */ + + /* If it is a CER, just reply an error */ + if (req) { + /* Create the error message */ + CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, MSGFL_ANSW_ERROR ) ); + + /* Set the error code */ + CHECK_FCT( fd_msg_rescode_set(*msg, "DIAMETER_COMMAND_UNSUPPORTED", "No CER in current state", NULL, 1 ) ); + + /* msg now contains an answer message to send back */ + CHECK_FCT_DO( fd_out_send(msg, peer->p_cnxctx, peer), /* In case of error the message has already been dumped */ ); + + } + + /* If the state is not WAITCEA, just discard the message */ + if ((req) || (peer->p_hdr.info.runtime.pir_state != STATE_WAITCEA)) { + if (*msg) { + fd_log_debug("Received CER/CEA message while in state '%s', discarded.\n", STATE_STR(peer->p_hdr.info.runtime.pir_state)); + fd_msg_dump_walk(NONE, *msg); + CHECK_FCT_DO( fd_msg_free(*msg), /* continue */); + *msg = NULL; + } + + return 0; + } + + /* Ok, now we can accept the CEA */ + TODO("process_valid_CEA"); + + return ENOTSUP; +} + +/* We have received a CER on a new connection for this peer */ int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid) { switch (peer->p_hdr.info.runtime.pir_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"); + TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake (OPEN_HANDSHAKE), move to OPEN or REOPEN state"); /* In case of error : DIAMETER_UNKNOWN_PEER */ break; case STATE_WAITCNXACK: + TODO("Save the parameters in the peer, move to STATE_WAITCNXACK_ELEC"); + break; + case STATE_WAITCEA: TODO("Election"); break; @@ -67,3 +129,38 @@ return ENOTSUP; } + +static int do_election(struct fd_peer * peer) +{ + TODO("Compare diameter Ids"); + + /* ELECTION_LOST error code ?*/ + + TODO("If we lost the election, we close the received connection and go to WAITCEA"); + TODO("If we won the election, we close initiator cnx, then call fd_p_ce_winelection"); + + +} + +/* We have established a new connection to the remote peer, send CER and eventually do election */ +int fd_p_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator) +{ + /* if not election */ + TODO("Set the connection as peer's (setaltfifo)"); + TODO("Send CER"); + TODO("Move to WAITCEA"); + TODO("Change timer to CEA_TIMEOUT"); + + /* if election */ + TODO("Send CER on cnx"); + TODO("Do the election"); + + return ENOTSUP; +} + +/* Handle the receiver side after winning an election (or timeout on initiator side) */ +int fd_p_ce_winelection(struct fd_peer * peer) +{ + TODO("Move the receiver side connection to peer principal, set the altfifo"); + TODO("Then handle the received CER"); +} diff -r d7535cf7bab5 -r 7e1deaa89540 freeDiameter/p_dp.c --- a/freeDiameter/p_dp.c Thu Nov 05 18:43:42 2009 +0900 +++ b/freeDiameter/p_dp.c Fri Nov 06 13:05:36 2009 +0900 @@ -38,7 +38,7 @@ /* 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) +int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer) { TODO("Handle depending on DPR or DPA and peer state"); diff -r d7535cf7bab5 -r 7e1deaa89540 freeDiameter/p_dw.c --- a/freeDiameter/p_dw.c Thu Nov 05 18:43:42 2009 +0900 +++ b/freeDiameter/p_dw.c Fri Nov 06 13:05:36 2009 +0900 @@ -39,7 +39,7 @@ /* Handle an incoming message */ -int fd_p_dw_handle(struct msg ** msg, struct fd_peer * peer) +int fd_p_dw_handle(struct msg ** msg, int req, struct fd_peer * peer) { TODO("Handle depending on DWR or DWA and peer state"); diff -r d7535cf7bab5 -r 7e1deaa89540 freeDiameter/p_psm.c --- a/freeDiameter/p_psm.c Thu Nov 05 18:43:42 2009 +0900 +++ b/freeDiameter/p_psm.c Fri Nov 06 13:05:36 2009 +0900 @@ -247,7 +247,6 @@ /* Move to CLOSED state: failover messages, stop OUT thread, unlink peer from active list */ CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ ); - fd_p_cnx_abort(peer, terminate); if (peer->p_cnxctx) { @@ -467,15 +466,15 @@ /* Handle the LL message and update the expiry timer appropriately */ switch (hdr->msg_code) { case CC_CAPABILITIES_EXCHANGE: - CHECK_FCT_DO( fd_p_ce_handle(&msg, peer), goto psm_end ); + CHECK_FCT_DO( fd_p_ce_msgrcv(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_end ); break; case CC_DISCONNECT_PEER: - CHECK_FCT_DO( fd_p_dp_handle(&msg, peer), goto psm_end ); + CHECK_FCT_DO( fd_p_dp_handle(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_end ); break; case CC_DEVICE_WATCHDOG: - CHECK_FCT_DO( fd_p_dw_handle(&msg, peer), goto psm_end ); + CHECK_FCT_DO( fd_p_dw_handle(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_end ); break; default: @@ -589,6 +588,29 @@ goto psm_loop; } + /* A new connection has been established with the remote peer */ + if (event == FDEVP_CNX_ESTABLISHED) { + struct cnxctx * cnx = ev_data; + + /* Release the resources of the thread */ + CHECK_POSIX_DO( pthread_join( peer->p_ini_thr, NULL), /* ignore, it is not a big deal */); + peer->p_ini_thr = (pthread_t)NULL; + + switch (peer->p_hdr.info.runtime.pir_state) { + case STATE_WAITCNXACK_ELEC: + case STATE_WAITCNXACK: + fd_p_ce_handle_newcnx(peer, cnx); + break; + + default: + /* Just abort the attempt and continue */ + TRACE_DEBUG(FULL, "Connection attempt successful but current state is %s, closing...", STATE_STR(peer->p_hdr.info.runtime.pir_state)); + fd_cnx_destroy(cnx); + } + + goto psm_loop; + } + /* The timeout for the current state has been reached */ if (event == FDEVP_PSM_TIMEOUT) { switch (peer->p_hdr.info.runtime.pir_state) { @@ -613,7 +635,12 @@ break; case STATE_WAITCNXACK_ELEC: - TODO("Abort initiating side, handle the receiver side"); + + /* Abort the initiating side */ + fd_p_cnx_abort(peer, 0); + + /* Handle receiver side */ + CHECK_FCT_DO( fd_p_ce_winelection(peer), goto psm_end ); break; } } @@ -621,7 +648,7 @@ /* Default action : the handling has not yet been implemented. [for debug only] */ TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.runtime.pir_state), fd_pev_str(event)); if (event == FDEVP_PSM_TIMEOUT) { - /* We have not handled timeout in this state, let's postpone next alert */ + /* We have not handled timeout in this state, let's postpone next alert to avoid flood */ fd_psm_next_timeout(peer, 0, 60); }