diff --git a/src/ac/ac_execute.c b/src/ac/ac_execute.c index 956ffe5..9a33f42 100644 --- a/src/ac/ac_execute.c +++ b/src/ac/ac_execute.c @@ -10,7 +10,7 @@ static void ac_session_add_packet(struct ac_session_t* session, char* buffer, int size, int isctrlsocket, int plainbuffer) { struct capwap_list_item* item; struct ac_packet* packet; - + ASSERT(session != NULL); ASSERT(buffer != NULL); ASSERT(size > 0); @@ -20,7 +20,7 @@ static void ac_session_add_packet(struct ac_session_t* session, char* buffer, in packet = (struct ac_packet*)item->item; packet->plainbuffer = plainbuffer; memcpy(packet->buffer, buffer, size); - + /* Append to packets list */ capwap_lock_enter(&session->packetslock); capwap_itemlist_insert_after((isctrlsocket ? session->controlpackets : session->datapackets), NULL, item); @@ -28,6 +28,32 @@ static void ac_session_add_packet(struct ac_session_t* session, char* buffer, in capwap_lock_exit(&session->packetslock); } +/* Add action to session */ +void ac_session_send_action(struct ac_session_t* session, long action, long param, void* data, long length) { + struct capwap_list_item* item; + struct ac_session_action* actionsession; + + ASSERT(session != NULL); + ASSERT(length >= 0); + + /* */ + item = capwap_itemlist_create(sizeof(struct ac_session_action) + length); + actionsession = (struct ac_session_action*)item->item; + actionsession->action = action; + actionsession->param = param; + actionsession->length = length; + if (length > 0) { + ASSERT(data != NULL); + memcpy(actionsession->data, data, length); + } + + /* Append to actions list */ + capwap_lock_enter(&session->packetslock); + capwap_itemlist_insert_after(session->actionsession, NULL, item); + capwap_event_signal(&session->waitpacket); + capwap_lock_exit(&session->packetslock); +} + /* Find AC sessions */ static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_storage* address, int isctrlsocket) { struct ac_session_t* result = NULL; @@ -183,8 +209,7 @@ static struct ac_session_t* ac_get_session_from_keepalive(void* buffer, int buff /* Close session */ static void ac_close_session(struct ac_session_t* session) { - session->closesession = 1; - capwap_event_signal(&session->waitpacket); + ac_session_send_action(session, AC_SESSION_ACTION_CLOSE, 0, NULL, 0); } /* Close sessions */ @@ -368,6 +393,7 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres capwap_event_init(&session->waitpacket); capwap_lock_init(&session->packetslock); + session->actionsession = capwap_list_create(); session->controlpackets = capwap_list_create(); session->datapackets = capwap_list_create(); session->requestfragmentpacket = capwap_list_create(); diff --git a/src/ac/ac_session.c b/src/ac/ac_session.c index b04a3c9..72fbbd5 100644 --- a/src/ac/ac_session.c +++ b/src/ac/ac_session.c @@ -4,8 +4,25 @@ #define PACKET_TIMEOUT -1 #define DTLS_SHUTDOWN -2 +#define ACTION_SESSION -3 +/* */ +static int ac_session_action_execute(struct ac_session_t* session, struct ac_session_action* action) { + int result = ACTION_SESSION; + + switch (action->action) { + case AC_SESSION_ACTION_CLOSE: { + result = DTLS_SHUTDOWN; + break; + } + } + + return result; +} + +/* */ static int ac_network_read(struct ac_session_t* session, void* buffer, int length, int* isctrlpacket, struct timeout_control* timeout) { + int result = 0; long indextimer; long waittimeout; @@ -15,15 +32,21 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt ASSERT(isctrlpacket != NULL); for (;;) { - if (session->closesession) { - session->closesession = 0; - return DTLS_SHUTDOWN; - } - capwap_lock_enter(&session->packetslock); - - if ((session->controlpackets->count > 0) || (session->datapackets->count > 0)) { - int result = 0; + + if (session->actionsession->count > 0) { + struct capwap_list_item* itemaction; + + itemaction = capwap_itemlist_remove_head(session->actionsession); + capwap_lock_exit(&session->packetslock); + + /* */ + result = ac_session_action_execute(session, (struct ac_session_action*)itemaction->item); + + /* Free packet */ + capwap_itemlist_free(itemaction); + return result; + } else if ((session->controlpackets->count > 0) || (session->datapackets->count > 0)) { struct capwap_list_item* itempacket; *isctrlpacket = ((session->controlpackets->count > 0) ? 1 : 0); @@ -435,6 +458,8 @@ static void ac_session_run(struct ac_session_t* session) { action = ac_dfa_execute(session, NULL); /* Timeout */ } else if (length == DTLS_SHUTDOWN) { action = ac_session_teardown_connection(session); + } else if (length == ACTION_SESSION) { + /* Nothing */ } } else if (length > 0) { /* Accept data packet only in running state */ @@ -585,6 +610,7 @@ int ac_session_release_reference(struct ac_session_t* session) { /* Free resource */ capwap_event_destroy(&session->waitpacket); capwap_lock_exit(&session->packetslock); + capwap_list_free(session->actionsession); capwap_list_free(session->controlpackets); capwap_list_free(session->datapackets); diff --git a/src/ac/ac_session.h b/src/ac/ac_session.h index 4ddffa5..63e2895 100644 --- a/src/ac/ac_session.h +++ b/src/ac/ac_session.h @@ -8,6 +8,9 @@ #define AC_DFA_DROP_PACKET 2 #define AC_DFA_DEAD 3 +/* */ +#define AC_SESSION_ACTION_CLOSE 0 + /* AC packet */ struct ac_packet { int plainbuffer; @@ -20,6 +23,14 @@ struct ac_session_control { unsigned short count; }; +/* */ +struct ac_session_action { + long action; + long param; + long length; + char data[0]; +}; + /* AC sessions */ struct ac_session_t { struct ac_state dfa; @@ -42,11 +53,11 @@ struct ac_session_t { struct capwap_dtls ctrldtls; struct capwap_dtls datadtls; - int closesession; pthread_t threadid; - + capwap_event_t waitpacket; capwap_lock_t packetslock; + struct capwap_list* actionsession; struct capwap_list* controlpackets; struct capwap_list* datapackets; @@ -69,6 +80,8 @@ void* ac_session_thread(void* param); int ac_session_teardown_connection(struct ac_session_t* session); int ac_session_release_reference(struct ac_session_t* session); +void ac_session_send_action(struct ac_session_t* session, long action, long param, void* data, long length); + void ac_dfa_change_state(struct ac_session_t* session, int state); void ac_get_control_information(struct capwap_list* controllist);