This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/src/session/session_transition.cpp

155 lines
5.5 KiB
C++
Raw Normal View History

#include <stdio.h>
#include <assert.h>
#include "session_transition.h"
#define MAX_TRANSITION_PER_STATE 4
struct session_transition
{
int inputs_mask;
enum session_state next_state;
} fsm[MAX_STATE][MAX_TRANSITION_PER_STATE];
/*
* session transition
*
* SESSION_STATE_INIT -> SESSION_STATE_INIT ( NONE )
* SESSION_STATE_INIT -> SESSION_STATE_OPENING ( TCP_SYN | TCP_SYN_ACK | UDP_DATA )
*
* SESSION_STATE_OPENING -> SESSION_STATE_OPENING ( NONE )
* SESSION_STATE_OPENING -> SESSION_STATE_ACTIVE ( TCP_DATA | UDP_DATA )
* SESSION_STATE_OPENING -> SESSION_STATE_CLOSING ( TCP_FIN | TCP_RST | TIMEOUT )
* SESSION_STATE_OPENING -> SESSION_STATE_CLOSED ( LRU_EVICT )
*
* SESSION_STATE_ACTIVE -> SESSION_STATE_ACTIVE ( NONE )
* SESSION_STATE_ACTIVE -> SESSION_STATE_CLOSING ( TCP_FIN | TCP_RST | TIMEOUT )
* SESSION_STATE_ACTIVE -> SESSION_STATE_CLOSED ( LRU_EVICT )
*
* SESSION_STATE_CLOSING -> SESSION_STATE_CLOSING ( NONE )
* SESSION_STATE_CLOSING -> SESSION_STATE_CLOSED ( TIMEOUT | LRU_EVICT )
*/
static void session_inputs_to_str(int inputs, char *buff, int len)
{
int nused = 0;
if (inputs & TCP_SYN)
{
nused += snprintf(buff + nused, len - nused, "TCP_SYN ");
}
if (inputs & TCP_SYN_ACK)
{
nused += snprintf(buff + nused, len - nused, "TCP_SYN_ACK ");
}
if (inputs & TCP_FIN)
{
nused += snprintf(buff + nused, len - nused, "TCP_FIN ");
}
if (inputs & TCP_RST)
{
nused += snprintf(buff + nused, len - nused, "TCP_RST ");
}
if (inputs & TCP_DATA)
{
nused += snprintf(buff + nused, len - nused, "TCP_DATA ");
}
if (inputs & UDP_DATA)
{
nused += snprintf(buff + nused, len - nused, "UDP_DATA ");
}
if (inputs & TIMEOUT)
{
nused += snprintf(buff + nused, len - nused, "TIMEOUT ");
}
if (inputs & LRU_EVICT)
{
nused += snprintf(buff + nused, len - nused, "LRU_EVICT ");
}
}
void session_transition_init()
{
// SESSION_STATE_INIT -> SESSION_STATE_OPENING ( TCP_SYN | TCP_SYN_ACK | UDP_DATA )
// SESSION_STATE_INIT -> SESSION_STATE_INIT ( NONE )
fsm[SESSION_STATE_INIT][0].inputs_mask = TCP_SYN | TCP_SYN_ACK | UDP_DATA;
fsm[SESSION_STATE_INIT][0].next_state = SESSION_STATE_OPENING;
fsm[SESSION_STATE_INIT][1].inputs_mask = NONE;
fsm[SESSION_STATE_INIT][1].next_state = SESSION_STATE_INIT;
// SESSION_STATE_OPENING -> SESSION_STATE_ACTIVE ( TCP_DATA | UDP_DATA )
// SESSION_STATE_OPENING -> SESSION_STATE_CLOSING ( TCP_FIN | TCP_RST | TIMEOUT )
// SESSION_STATE_OPENING -> SESSION_STATE_CLOSED ( LRU_EVICT )
// SESSION_STATE_OPENING -> SESSION_STATE_OPENING ( NONE )
fsm[SESSION_STATE_OPENING][0].inputs_mask = TCP_DATA | UDP_DATA;
fsm[SESSION_STATE_OPENING][0].next_state = SESSION_STATE_ACTIVE;
fsm[SESSION_STATE_OPENING][1].inputs_mask = TCP_FIN | TCP_RST | TIMEOUT;
fsm[SESSION_STATE_OPENING][1].next_state = SESSION_STATE_CLOSING;
fsm[SESSION_STATE_OPENING][2].inputs_mask = LRU_EVICT;
fsm[SESSION_STATE_OPENING][2].next_state = SESSION_STATE_CLOSED;
fsm[SESSION_STATE_OPENING][3].inputs_mask = NONE;
fsm[SESSION_STATE_OPENING][3].next_state = SESSION_STATE_OPENING;
// SESSION_STATE_ACTIVE -> SESSION_STATE_CLOSING ( TCP_FIN | TCP_RST | TIMEOUT )
// SESSION_STATE_ACTIVE -> SESSION_STATE_CLOSED ( LRU_EVICT )
// SESSION_STATE_ACTIVE -> SESSION_STATE_ACTIVE ( NONE )
fsm[SESSION_STATE_ACTIVE][0].inputs_mask = TCP_FIN | TCP_RST | TIMEOUT;
fsm[SESSION_STATE_ACTIVE][0].next_state = SESSION_STATE_CLOSING;
fsm[SESSION_STATE_ACTIVE][1].inputs_mask = LRU_EVICT;
fsm[SESSION_STATE_ACTIVE][1].next_state = SESSION_STATE_CLOSED;
fsm[SESSION_STATE_ACTIVE][2].inputs_mask = NONE;
fsm[SESSION_STATE_ACTIVE][2].next_state = SESSION_STATE_ACTIVE;
// SESSION_STATE_CLOSING -> SESSION_STATE_CLOSED ( TIMEOUT | LRU_EVICT )
// SESSION_STATE_CLOSING -> SESSION_STATE_CLOSING ( NONE )
fsm[SESSION_STATE_CLOSING][0].inputs_mask = TIMEOUT | LRU_EVICT;
fsm[SESSION_STATE_CLOSING][0].next_state = SESSION_STATE_CLOSED;
fsm[SESSION_STATE_CLOSING][1].inputs_mask = NONE;
fsm[SESSION_STATE_CLOSING][1].next_state = SESSION_STATE_CLOSING;
}
enum session_state session_transition_run(enum session_state curr_state, int inputs)
{
struct session_transition *list = fsm[curr_state];
for (int i = 0; i < MAX_TRANSITION_PER_STATE; i++)
{
int mask = list[i].inputs_mask;
if (mask & inputs)
{
return list[i].next_state;
}
if (mask == NONE)
{
return list[i].next_state;
}
}
assert(0);
return curr_state;
}
void session_transition_log(struct session *sess, enum session_state curr_state, enum session_state next_state, int inputs)
{
if (curr_state == next_state)
{
return;
}
char buff[128] = {0};
char reason[128] = {0};
tuple6_to_str(session_get0_key(sess), buff, sizeof(buff));
session_inputs_to_str(inputs, reason, sizeof(reason));
SESSION_TRANSITION_LOG_DEBUG("%s session %lu %s (%s) %s -> %s",
session_type_to_str(session_get_type(sess)), session_get_id(sess), buff, reason,
session_state_to_str(curr_state), session_state_to_str(next_state));
}