Reengineering the timeout manager. Allows to create an arbitrary number of timer

with the possibility to invoke a callback function on timeout.
This commit is contained in:
vemax78
2014-03-02 19:31:27 +01:00
parent aa87719432
commit 6042161d75
31 changed files with 1259 additions and 1138 deletions

View File

@ -48,22 +48,16 @@ static int ac_init(void) {
g_ac.dfa.transport.type = CAPWAP_UDP_TRANSPORT;
/* */
g_ac.dfa.timers.discovery = AC_DEFAULT_DISCOVERY_INTERVAL;
g_ac.dfa.timers.echorequest = AC_DEFAULT_ECHO_INTERVAL;
g_ac.dfa.decrypterrorreport_interval = AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL;
g_ac.dfa.idletimeout.timeout = AC_DEFAULT_IDLE_TIMEOUT_INTERVAL;
g_ac.dfa.wtpfallback.mode = AC_DEFAULT_WTP_FALLBACK_MODE;
g_ac.dfa.timers.discovery = AC_DISCOVERY_INTERVAL / 1000;
g_ac.dfa.timers.echorequest = AC_ECHO_INTERVAL / 1000;
g_ac.dfa.decrypterrorreport_interval = AC_DECRYPT_ERROR_PERIOD_INTERVAL / 1000;
g_ac.dfa.idletimeout.timeout = AC_IDLE_TIMEOUT_INTERVAL / 1000;
g_ac.dfa.wtpfallback.mode = AC_WTP_FALLBACK_MODE;
/* */
g_ac.dfa.acipv4list.addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);
g_ac.dfa.acipv6list.addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);
/* */
g_ac.dfa.rfcWaitJoin = AC_DEFAULT_WAITJOIN_INTERVAL;
g_ac.dfa.rfcWaitDTLS = AC_DEFAULT_WAITDTLS_INTERVAL;
g_ac.dfa.rfcChangeStatePendingTimer = AC_DEFAULT_CHANGE_STATE_PENDING_TIMER;
g_ac.dfa.rfcDataCheckTimer = AC_DEFAULT_DATA_CHECK_TIMER;
/* Sessions */
g_ac.sessions = capwap_list_create();
g_ac.sessionsdata = capwap_list_create();
@ -352,8 +346,9 @@ static int ac_parsing_configuration_1_0(config_t* config) {
/* Set Timer of AC */
if (config_lookup_int(config, "application.timer.discovery", &configInt) == CONFIG_TRUE) {
if ((configInt >= AC_DEFAULT_DISCOVERY_INTERVAL) && (configInt <= AC_MAX_DISCOVERY_INTERVAL)) {
g_ac.dfa.timers.discovery = (unsigned char)configInt;
configInt *= 1000; /* Set timeout in ms */
if ((configInt >= AC_MIN_DISCOVERY_INTERVAL) && (configInt <= AC_MAX_DISCOVERY_INTERVAL)) {
g_ac.dfa.timers.discovery = (unsigned char)(configInt / 1000);
} else {
capwap_logging_error("Invalid configuration file, invalid application.timer.discovery value");
return 0;
@ -361,8 +356,9 @@ static int ac_parsing_configuration_1_0(config_t* config) {
}
if (config_lookup_int(config, "application.timer.echorequest", &configInt) == CONFIG_TRUE) {
if ((configInt > 0) && (configInt < AC_MAX_ECHO_INTERVAL)) {
g_ac.dfa.timers.echorequest = (unsigned char)configInt;
configInt *= 1000;
if ((configInt >= AC_MIN_ECHO_INTERVAL) && (configInt <= AC_MAX_ECHO_INTERVAL)) {
g_ac.dfa.timers.echorequest = (unsigned char)(configInt / 1000);
} else {
capwap_logging_error("Invalid configuration file, invalid application.timer.echorequest value");
return 0;

View File

@ -26,31 +26,37 @@
#define AC_ERROR_MEMORY_LEAK 1
/* Min and max dfa values */
#define AC_MIN_WAITDTLS_INTERVAL 30
#define AC_DEFAULT_WAITDTLS_INTERVAL 60
#define AC_MIN_WAITJOIN_INTERVAL 20
#define AC_DEFAULT_WAITJOIN_INTERVAL 60
#define AC_DEFAULT_CHANGE_STATE_PENDING_TIMER 25
#define AC_MIN_DISCOVERY_INTERVAL 2
#define AC_DEFAULT_DISCOVERY_INTERVAL 20
#define AC_MAX_DISCOVERY_INTERVAL 180
#define AC_DEFAULT_ECHO_INTERVAL 30
#define AC_MAX_ECHO_INTERVAL 256
#define AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL 120
#define AC_DEFAULT_IDLE_TIMEOUT_INTERVAL 300
#define AC_DEFAULT_WTP_FALLBACK_MODE CAPWAP_WTP_FALLBACK_ENABLED
#define AC_DEFAULT_DATA_CHECK_TIMER 30
#define AC_MAX_DATA_CHECK_TIMER 256
#define AC_DEFAULT_RETRANSMIT_INTERVAL 3
#define AC_MAX_RETRANSMIT 5
#define AC_DEFAULT_DTLS_SESSION_DELETE 5
#define AC_DTLS_INTERVAL 60000
/* AC DFA */
#define AC_JOIN_INTERVAL 60000
#define AC_CHANGE_STATE_PENDING_INTERVAL 25000
#define AC_DATA_CHECK_INTERVAL 30000
#define AC_RETRANSMIT_INTERVAL 3000
#define AC_MAX_RETRANSMIT 5
#define AC_DTLS_SESSION_DELETE_INTERVAL 5000
#define AC_MIN_ECHO_INTERVAL 1000
#define AC_ECHO_INTERVAL 30000
#define AC_MAX_ECHO_INTERVAL 256000
#define AC_MAX_DATA_KEEPALIVE_INTERVAL 256000
#define AC_MIN_DISCOVERY_INTERVAL 2000
#define AC_DISCOVERY_INTERVAL 20000
#define AC_MAX_DISCOVERY_INTERVAL 180000
#define AC_DECRYPT_ERROR_PERIOD_INTERVAL 120000
#define AC_IDLE_TIMEOUT_INTERVAL 300000
#define AC_WTP_FALLBACK_MODE CAPWAP_WTP_FALLBACK_ENABLED
/* */
struct ac_state {
/* */
struct capwap_ecnsupport_element ecn;
struct capwap_transport_element transport;
struct capwap_timers_element timers;
unsigned short decrypterrorreport_interval;
struct capwap_idletimeout_element idletimeout;
@ -59,20 +65,6 @@ struct ac_state {
/* */
struct capwap_acipv4list_element acipv4list;
struct capwap_acipv6list_element acipv6list;
/* */
int rfcWaitJoin;
int rfcChangeStatePendingTimer;
int rfcDataCheckTimer;
int rfcDTLSSessionDelete;
/* Request retransmit */
int rfcRetransmitInterval;
int rfcRetransmitCount;
int rfcMaxRetransmit;
/* Dtls */
int rfcWaitDTLS;
};
/* AC */

View File

@ -708,66 +708,61 @@ static uint32_t ac_dfa_state_configure_create_response(struct ac_session_t* sess
/* */
void ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
ASSERT(session != NULL);
if (packet) {
struct ac_soap_response* response;
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
ASSERT(packet != NULL);
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Parsing request and add message element for respone message */
response = ac_dfa_state_configure_parsing_request(session, packet);
if (response) {
result = ac_dfa_state_configure_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
/* Parsing request and add message element for respone message */
response = ac_dfa_state_configure_parsing_request(session, packet);
if (response) {
result = ac_dfa_state_configure_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
}
/* With error add result code message element */
if (!CAPWAP_RESULTCODE_OK(result)) {
struct capwap_resultcode_element resultcode = { .code = result };
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* */
if (result == CAPWAP_RESULTCODE_FAILURE) {
/* TODO: Add AC List Message Elements */
}
}
/* With error add result code message element */
if (!CAPWAP_RESULTCODE_OK(result)) {
struct capwap_resultcode_element resultcode = { .code = result };
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* Configure response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* */
if (result == CAPWAP_RESULTCODE_FAILURE) {
/* TODO: Add AC List Message Elements */
}
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Configure response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Send Configure response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send configuration status response packet");
}
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Send Configure response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send configuration status response packet");
}
/* Change state */
if (CAPWAP_RESULTCODE_OK(result)) {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
capwap_timeout_set(session->dfa.rfcChangeStatePendingTimer, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_session_teardown(session);
}
/* Change state */
if (CAPWAP_RESULTCODE_OK(result)) {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_CHANGE_STATE_PENDING_INTERVAL, ac_dfa_state_datacheck_timeout, session, NULL);
} else {
/* Configure timeout */
ac_session_teardown(session);
}
}

View File

@ -172,68 +172,68 @@ static uint32_t ac_dfa_state_datacheck_create_response(struct ac_session_t* sess
return CAPWAP_RESULTCODE_SUCCESS;
}
/* */
void ac_dfa_state_datacheck_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
ac_session_teardown((struct ac_session_t*)context); /* Configure timeout */
}
/* */
void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
ASSERT(session != NULL);
if (packet) {
struct ac_soap_response* response;
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
ASSERT(packet != NULL);
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Parsing request and add message element for respone message */
response = ac_dfa_state_datacheck_parsing_request(session, packet);
if (response) {
result = ac_dfa_state_datacheck_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
/* Parsing request and add message element for respone message */
response = ac_dfa_state_datacheck_parsing_request(session, packet);
if (response) {
result = ac_dfa_state_datacheck_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
}
/* With error add result code message element */
if (!CAPWAP_RESULTCODE_OK(result)) {
struct capwap_resultcode_element resultcode = { .code = result };
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* */
if (result == CAPWAP_RESULTCODE_FAILURE) {
/* TODO: Add AC List Message Elements */
}
}
/* With error add result code message element */
if (!CAPWAP_RESULTCODE_OK(result)) {
struct capwap_resultcode_element resultcode = { .code = result };
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* Change event response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* */
if (result == CAPWAP_RESULTCODE_FAILURE) {
/* TODO: Add AC List Message Elements */
}
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Change event response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Send Change event response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send change event response packet");
}
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Send Change event response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send change event response packet");
}
/* Change state */
if (CAPWAP_RESULTCODE_OK(result)) {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
capwap_timeout_set(session->dfa.rfcDataCheckTimer, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_session_teardown(session);
}
/* Change state */
if (CAPWAP_RESULTCODE_OK(result)) {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_DATA_CHECK_INTERVAL, ac_dfa_state_datacheck_timeout, session, NULL);
} else {
/* Configure timeout */
ac_session_teardown(session);
}
}
@ -242,7 +242,5 @@ void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_p
void ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
if (!packet) {
ac_session_teardown(session); /* Configure timeout */
}
ac_session_teardown(session);
}

View File

@ -21,6 +21,11 @@ static int ac_bio_data_send(struct capwap_dtls* dtls, char* buffer, int length,
return capwap_sendto(sessiondata->connection.socket.socket[sessiondata->connection.socket.type], buffer, length, &sessiondata->connection.localaddr, &sessiondata->connection.remoteaddr);
}
/* */
void ac_dtls_setup_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
ac_session_teardown((struct ac_session_t*)context); /* Configure timeout */
}
/* */
int ac_dtls_setup(struct ac_session_t* session) {
ASSERT(session != NULL);
@ -36,7 +41,7 @@ int ac_dtls_setup(struct ac_session_t* session) {
/* Wait DTLS handshake complete */
ac_dfa_change_state(session, CAPWAP_DTLS_CONNECT_STATE);
capwap_timeout_set(session->dfa.rfcWaitDTLS, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_DTLS_INTERVAL, ac_dtls_setup_timeout, session, NULL);
return 1;
}

View File

@ -6,4 +6,5 @@
/* */
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
/* TODO */
ac_session_teardown(session);
}

View File

@ -578,8 +578,14 @@ static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session,
return CAPWAP_RESULTCODE_SUCCESS;
}
/* */
void ac_dfa_state_join_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
ac_session_teardown((struct ac_session_t*)context); /* Join timeout */
}
/* */
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
unsigned short binding;
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
@ -588,99 +594,94 @@ void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet
struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE };
ASSERT(session != NULL);
if (packet) {
unsigned short binding;
ASSERT(packet != NULL);
/* Check binding */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if (ac_valid_binding(binding)) {
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) {
/* Get sessionid and verify unique id */
sessionid = (struct capwap_sessionid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_SESSIONID);
if (!ac_has_sessionid(sessionid)) {
char* wtpid;
/* Check binding */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if (ac_valid_binding(binding)) {
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) {
/* Get sessionid and verify unique id */
sessionid = (struct capwap_sessionid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_SESSIONID);
if (!ac_has_sessionid(sessionid)) {
char* wtpid;
/* Checking macaddress for detect if WTP already connected */
wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA);
/* Checking macaddress for detect if WTP already connected */
wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA);
/* Get printable WTPID */
wtpid = ac_get_printable_wtpid(wtpboarddata);
if (wtpid && !ac_has_wtpid(wtpid)) {
/* Request authorization of Backend for complete join */
response = ac_soap_authorizewtpsession(session, wtpid);
if (response) {
resultcode.code = ac_dfa_state_join_check_authorizejoin(session, response);
ac_soapclient_free_response(response);
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
}
/* Get printable WTPID */
wtpid = ac_get_printable_wtpid(wtpboarddata);
if (wtpid && !ac_has_wtpid(wtpid)) {
/* Request authorization of Backend for complete join */
response = ac_soap_authorizewtpsession(session, wtpid);
if (response) {
resultcode.code = ac_dfa_state_join_check_authorizejoin(session, response);
ac_soapclient_free_response(response);
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
}
/* */
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
session->wtpid = wtpid;
memcpy(&session->sessionid, sessionid, sizeof(struct capwap_sessionid_element));
session->binding = binding;
} else {
capwap_free(wtpid);
}
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE;
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
}
/* */
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
session->wtpid = wtpid;
memcpy(&session->sessionid, sessionid, sizeof(struct capwap_sessionid_element));
session->binding = binding;
} else {
capwap_free(wtpid);
}
} else {
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE;
}
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
}
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
}
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_JOIN_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_JOIN_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* */
/* */
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
response = ac_dfa_state_join_parsing_request(session, packet);
if (response) {
resultcode.code = ac_dfa_state_join_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
}
}
/* Add always result code message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* Join response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Send Join response to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
response = ac_dfa_state_join_parsing_request(session, packet);
if (response) {
resultcode.code = ac_dfa_state_join_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
}
}
/* Add always result code message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* Join response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Send Join response to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
} else {
ac_session_teardown(session);
}
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_state_join_timeout, session, NULL);
} else {
/* Error to send packets */
capwap_logging_debug("Warning: error to send join response packet");
ac_session_teardown(session);
}
} else {
/* Join timeout */
/* Error to send packets */
capwap_logging_debug("Warning: error to send join response packet");
ac_session_teardown(session);
}
}
@ -688,19 +689,15 @@ void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet
/* */
void ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet != NULL);
if (packet) {
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
ac_dfa_state_configure(session, packet);
} else if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_IMAGE_DATA_REQUEST) {
ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE);
ac_dfa_state_imagedata(session, packet);
} else {
ac_session_teardown(session);
}
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
ac_dfa_state_configure(session, packet);
} else if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_IMAGE_DATA_REQUEST) {
ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE);
ac_dfa_state_imagedata(session, packet);
} else {
/* Join timeout */
ac_session_teardown(session);
}
}

View File

@ -5,41 +5,23 @@
/* */
void ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
unsigned short binding;
if (packet) {
unsigned short binding;
ASSERT(session != NULL);
ASSERT(packet != NULL);
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if ((binding == session->binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) {
struct capwap_resultcode_element* resultcode;
/* Check the success of the Request */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
capwap_logging_warning("Receive Reset Response with error: %d", (int)resultcode->code);
}
/* */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if ((binding == session->binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) {
struct capwap_resultcode_element* resultcode;
/* Check the success of the Request */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
capwap_logging_warning("Receive Reset Response with error: %d", (int)resultcode->code);
}
/* */
ac_free_reference_last_request(session);
ac_session_teardown(session);
}
} else {
/* No Reset Response received */
session->dfa.rfcRetransmitCount++;
if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) {
/* Timeout reset state */
ac_free_reference_last_request(session);
ac_session_teardown(session);
} else {
/* Retransmit Reset Request */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
capwap_logging_debug("Warning: error to resend reset request packet");
}
/* Update timeout */
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
ac_free_reference_last_request(session);
ac_session_teardown(session);
}
}

View File

@ -78,94 +78,75 @@ static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* s
/* */
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet != NULL);
if (packet) {
if (capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type) || ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) {
switch (packet->rxmngpacket->ctrlmsg.type) {
case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: {
/* TODO */
if (capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type) || ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) {
switch (packet->rxmngpacket->ctrlmsg.type) {
case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_CHANGE_STATE_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_ECHO_REQUEST: {
if (!receive_echo_request(session, packet)) {
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_session_teardown(session);
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_WTP_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: {
receive_ieee80211_wlan_configuration_response(session, packet);
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
}
}
} else if ((session->requestfragmentpacket->count > 0)) {
/* No response received */
session->dfa.rfcRetransmitCount++;
if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) {
/* Timeout */
ac_free_reference_last_request(session);
ac_session_teardown(session);
} else {
/* Retransmit request */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
capwap_logging_debug("Warning: error to resend request packet");
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
/* Update timeout */
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
case CAPWAP_CHANGE_STATE_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_ECHO_REQUEST: {
if (!receive_echo_request(session, packet)) {
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
} else {
ac_session_teardown(session);
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_WTP_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: {
receive_ieee80211_wlan_configuration_response(session, packet);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
}
} else {
ac_session_teardown(session);
}
}

View File

@ -503,16 +503,13 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
/* */
session->timeout = capwap_timeout_init();
session->idtimercontrol = capwap_timeout_createtimer(session->timeout);
/* Duplicate state for DFA */
memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state));
session->dfa.acipv4list.addresses = capwap_array_clone(g_ac.dfa.acipv4list.addresses);
session->dfa.acipv6list.addresses = capwap_array_clone(g_ac.dfa.acipv6list.addresses);
session->dfa.rfcRetransmitInterval = AC_DEFAULT_RETRANSMIT_INTERVAL;
session->dfa.rfcMaxRetransmit = AC_MAX_RETRANSMIT;
session->dfa.rfcDTLSSessionDelete = AC_DEFAULT_DTLS_SESSION_DELETE;
/* Add default AC list if empty*/
if ((session->dfa.acipv4list.addresses->count == 0) && (session->dfa.acipv6list.addresses->count == 0)) {
if (acaddress->ss_family == AF_INET) {
@ -588,6 +585,8 @@ static struct ac_session_data_t* ac_create_session_data(struct sockaddr_storage*
/* */
sessiondata->timeout = capwap_timeout_init();
sessiondata->idtimercontrol = capwap_timeout_createtimer(sessiondata->timeout);
sessiondata->idtimerkeepalivedead = capwap_timeout_createtimer(sessiondata->timeout);
/* Connection info */
memcpy(&sessiondata->connection.socket, sock, sizeof(struct capwap_socket));

View File

@ -39,10 +39,9 @@ static int ac_session_action_resetwtp(struct ac_session_t* session, struct ac_no
/* Send Reset Request to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
session->dfa.rfcRetransmitCount = 0;
capwap_timeout_killall(session->timeout);
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
session->retransmitcount = 0;
ac_dfa_change_state(session, CAPWAP_RESET_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
} else {
capwap_logging_debug("Warning: error to send reset request packet");
ac_free_reference_last_request(session);
@ -94,9 +93,8 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not
/* Send WLAN Configuration Request to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
session->dfa.rfcRetransmitCount = 0;
capwap_timeout_killall(session->timeout);
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
session->retransmitcount = 0;
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
} else {
capwap_logging_debug("Warning: error to send reset request packet");
ac_free_reference_last_request(session);
@ -139,7 +137,7 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses
if (valid) {
ac_dfa_change_state(session, CAPWAP_RUN_STATE);
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
} else {
result = CAPWAP_ERROR_CLOSE;
}
@ -165,7 +163,6 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses
/* */
static int ac_network_read(struct ac_session_t* session, void* buffer, int length) {
int result = 0;
long indextimer;
long waittimeout;
ASSERT(session != NULL);
@ -213,7 +210,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (session->dtls.action == CAPWAP_DTLS_ACTION_DATA)) {
if (session->state == CAPWAP_DTLS_CONNECT_STATE) {
ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
capwap_timeout_set(session->dfa.rfcWaitJoin, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_state_join_timeout, session, NULL);
}
}
}
@ -233,10 +230,10 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
capwap_lock_exit(&session->sessionlock);
/* Update timeout */
capwap_timeout_update(session->timeout);
waittimeout = capwap_timeout_get(session->timeout, &indextimer);
if ((waittimeout <= 0) && (indextimer != CAPWAP_TIMER_UNDEF)) {
/* Get timeout */
waittimeout = capwap_timeout_getcoming(session->timeout);
if (!waittimeout) {
capwap_timeout_hasexpired(session->timeout);
return AC_ERROR_TIMEOUT;
}
@ -250,6 +247,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
/* */
static void ac_dfa_execute(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet != NULL);
/* Execute state */
switch (session->state) {
@ -481,16 +479,14 @@ static void ac_session_run(struct ac_session_t* session) {
} else {
/* Wait Join request */
ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
capwap_timeout_set(session->dfa.rfcWaitJoin, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_state_join_timeout, session, NULL);
}
while (session->state != CAPWAP_DTLS_TEARDOWN_STATE) {
/* Get packet */
length = ac_network_read(session, buffer, sizeof(buffer));
if (length < 0) {
if (length == AC_ERROR_TIMEOUT) {
ac_dfa_execute(session, NULL);
} else if ((length == CAPWAP_ERROR_SHUTDOWN) || (length == CAPWAP_ERROR_CLOSE)) {
if ((length == CAPWAP_ERROR_SHUTDOWN) || (length == CAPWAP_ERROR_CLOSE)) {
ac_session_teardown(session);
}
} else if (length > 0) {
@ -602,7 +598,7 @@ static void ac_session_run(struct ac_session_t* session) {
}
/* Wait teardown timeout before kill session */
capwap_timeout_wait(session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
capwap_timeout_wait(AC_DTLS_SESSION_DELETE_INTERVAL);
ac_dfa_state_teardown(session);
/* Release reference session */
@ -668,11 +664,6 @@ void ac_session_teardown(struct ac_session_t* session) {
capwap_crypt_close(&session->dtls);
}
/* */
capwap_timeout_killall(session->timeout);
capwap_timeout_set(session->dfa.rfcDTLSSessionDelete, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE);
/* Cancel all notify event */
if (session->notifyevent->first) {
char buffer[5];
@ -692,6 +683,10 @@ void ac_session_teardown(struct ac_session_t* session) {
capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, session->notifyevent->first));
}
}
/* */
ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE);
capwap_timeout_unset(session->timeout, session->idtimercontrol);
}
/* */
@ -835,3 +830,32 @@ struct ac_soap_response* ac_session_send_soap_request(struct ac_session_t* sessi
return response;
}
/* */
void ac_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
struct ac_session_t* session = (struct ac_session_t*)context;
if (!session->requestfragmentpacket->count) {
ac_session_teardown(session);
} else {
session->retransmitcount++;
if (session->retransmitcount >= AC_MAX_RETRANSMIT) {
/* Timeout reset state */
ac_free_reference_last_request(session);
ac_session_teardown(session);
} else {
/* Retransmit Reset Request */
capwap_logging_debug("Retransmition request packet");
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
capwap_logging_error("Error to send request packet");
}
/* Update timeout */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
}
}
}
void ac_dfa_teardown_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
ac_session_teardown((struct ac_session_t*)context);
}

View File

@ -66,7 +66,10 @@ struct ac_session_data_t {
unsigned short mtu;
struct capwap_connection connection;
struct capwap_dtls dtls;
struct timeout_control* timeout;
struct capwap_timeout* timeout;
unsigned long idtimercontrol;
unsigned long idtimerkeepalivedead;
capwap_event_t waitpacket;
capwap_lock_t sessionlock;
@ -105,7 +108,9 @@ struct ac_session_t {
unsigned short mtu;
struct capwap_dtls dtls;
struct capwap_connection connection;
struct timeout_control* timeout;
struct capwap_timeout* timeout;
unsigned long idtimercontrol;
capwap_event_t waitpacket;
capwap_lock_t sessionlock;
@ -121,6 +126,7 @@ struct ac_session_t {
struct capwap_list* requestfragmentpacket;
struct capwap_list* responsefragmentpacket;
unsigned char lastrecvpackethash[16];
int retransmitcount;
};
/* Session */
@ -162,16 +168,29 @@ void ac_msgqueue_notify_closethread(pthread_t threadid);
/* */
int ac_dtls_setup(struct ac_session_t* session);
int ac_dtls_data_setup(struct ac_session_data_t* sessiondata);
void ac_dtls_setup_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
/* */
void ac_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void ac_dfa_teardown_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
/* */
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_join_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_datacheck_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_teardown(struct ac_session_t* session);
/* Soap function */

View File

@ -17,7 +17,6 @@ static int ac_session_data_action_execute(struct ac_session_data_t* sessiondata,
/* */
static int ac_network_read(struct ac_session_data_t* sessiondata, void* buffer, int length) {
long indextimer;
long waittimeout;
int result = CAPWAP_ERROR_AGAIN;
@ -63,8 +62,8 @@ static int ac_network_read(struct ac_session_data_t* sessiondata, void* buffer,
if (result == CAPWAP_ERROR_AGAIN) {
/* Check is handshake complete */
if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (sessiondata->dtls.action == CAPWAP_DTLS_ACTION_DATA)) {
capwap_timeout_kill(sessiondata->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
capwap_timeout_set(AC_MAX_DATA_CHECK_TIMER, sessiondata->timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD);
capwap_timeout_unset(sessiondata->timeout, sessiondata->idtimercontrol);
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, NULL, NULL, NULL);
}
}
} else {
@ -83,10 +82,10 @@ static int ac_network_read(struct ac_session_data_t* sessiondata, void* buffer,
capwap_lock_exit(&sessiondata->sessionlock);
/* Update timeout */
capwap_timeout_update(sessiondata->timeout);
waittimeout = capwap_timeout_get(sessiondata->timeout, &indextimer);
if ((waittimeout <= 0) && (indextimer != CAPWAP_TIMER_UNDEF)) {
/* Get timeout */
waittimeout = capwap_timeout_getcoming(sessiondata->timeout);
if (!waittimeout) {
capwap_timeout_hasexpired(sessiondata->timeout);
return AC_ERROR_TIMEOUT;
}
@ -312,13 +311,13 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
/* Create DTLS channel */
if (sessiondata->enabledtls) {
if (ac_dtls_data_setup(sessiondata)) {
capwap_timeout_set(AC_DEFAULT_WAITDTLS_INTERVAL, sessiondata->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimercontrol, AC_DTLS_INTERVAL, NULL, NULL, NULL);
} else {
capwap_logging_debug("Unable to start DTLS data");
sessiondata->running = 0;
}
} else {
capwap_timeout_set(AC_MAX_DATA_CHECK_TIMER, sessiondata->timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD);
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, NULL, NULL, NULL);
}
/* */
@ -356,7 +355,7 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
ac_session_data_keepalive(sessiondata, &packet);
/* Update timeout */
capwap_timeout_set(AC_MAX_DATA_CHECK_TIMER, sessiondata->timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD);
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, NULL, NULL, NULL);
} else {
/* TODO */
}