Author: tjansen Date: Wed Oct 21 16:15:11 2009 New Revision: 1259 Log: Switched pisasd heartbeat handling to the scheduler. Modified: trunk/pisasd/sdheartbeat.c trunk/pisasd/sdheartbeat.h trunk/pisasd/sdmain.c trunk/pisasd/sdregister.c trunk/pisasd/sdtun.c Modified: trunk/pisasd/sdheartbeat.c ============================================================================== --- trunk/pisasd/sdheartbeat.c Wed Oct 21 15:11:11 2009 (r1258) +++ trunk/pisasd/sdheartbeat.c Wed Oct 21 16:15:11 2009 (r1259) @@ -12,46 +12,31 @@ */ #include "sdctx.h" +#include "sdheartbeat.h" /** - * Time to wait until a connection is removed from the internal list of life connections. - * @sa removeTimedoutConnectionsFlag - * @sa process - */ -static time_t waitingPeriod = 60; - -/** - * Check if a connection has timed out and remove it. - * @param data pointer to the current time (only provided this way to avoid having to call - * time() several times) - * @param entry entry connection which is to be examined - */ -static void cb_check_timeout(void* data,pisa_conmgr_entry* entry) + * Check a connection for its last received time to see if we want to throw + * idle connections away. */ +void pisa_task_heartbeat(void *data) { - char buffer[INET6_ADDRSTRLEN]; - time_t currentTime = *((time_t*)data); + struct timeval delay = {PISA_HEARTBEAT_DELAY, 0}; + pisa_conmgr_entry *e = (pisa_conmgr_entry *)data; + + e->heartbeat_task = NULL; - if ((entry->timeout_heartbeat + waitingPeriod) < currentTime) { - inet_ntop(AF_INET6, &entry->hit, buffer, sizeof(buffer)); + /* If we did not receive data or a heartbeat from the client in the + * last window remove the connection. There is no need to reschedule + * in that case. */ + if (e->heartbeat_flag == 0) { + char buffer[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &e->hit, buffer, sizeof(buffer)); PISA_INFO("Removing timed out client %s\n", buffer); - pisa_conmgr_remove(sd_ctx.conlist, sd_ctx.natlist, entry); + pisa_conmgr_remove(sd_ctx.conlist, sd_ctx.natlist, e); + return; } -} - -/** - * Remove all connections from our internal list that have timed out. - * Only check every 10 seconds for it. - */ -void pisa_sd_timeout_collect(void) -{ - static time_t last = 0; - time_t current; - time(¤t); - if (last + 10 < current) { - pisa_conmgr_iterate(sd_ctx.conlist, cb_check_timeout, ¤t); - last = current; - } + e->heartbeat_flag = 0; + e->heartbeat_task = pisa_sched_add(&sd_ctx.scheduler, pisa_task_heartbeat, &delay, e); } /** @@ -66,7 +51,7 @@ pisa_conmgr_entry *e = pisa_conmgr_findby_address(sd_ctx.conlist, &addr->sin6_addr); if (e) { - time(&e->timeout_heartbeat); + e->heartbeat_flag = 1; pisa_send_control_packet_ipv6_type(sd_ctx.tunc, addr, PISA_PKTTYPE_TUN_HEARTBEAT_ACK); inet_ntop(AF_INET6, &addr->sin6_addr, buffer, sizeof(buffer)); PISA_INFO("Heartbeat from client %s\n", buffer); Modified: trunk/pisasd/sdheartbeat.h ============================================================================== --- trunk/pisasd/sdheartbeat.h Wed Oct 21 15:11:11 2009 (r1258) +++ trunk/pisasd/sdheartbeat.h Wed Oct 21 16:15:11 2009 (r1259) @@ -16,12 +16,10 @@ #define PISA_SDHEARTBEAT_H #include "packet.h" -#include "conmgr.h" -/** - * Function prototypes - */ -void pisa_sd_timeout_collect(void); +#define PISA_HEARTBEAT_DELAY 60 + +void pisa_task_heartbeat(void *data); /* handlers for tunnel control packets */ void pisa_recv_heartbeat(pisa_packet *pkt, struct sockaddr_in6 *addr); Modified: trunk/pisasd/sdmain.c ============================================================================== --- trunk/pisasd/sdmain.c Wed Oct 21 15:11:11 2009 (r1258) +++ trunk/pisasd/sdmain.c Wed Oct 21 16:15:11 2009 (r1259) @@ -113,6 +113,18 @@ } /** + * A connection is removed permanently from the list. Clean up all associated + * state. + * + * @param entry The entry associated with this connection + */ +void pisasd_cleanup_after_removed_connection(pisa_conmgr_entry* entry) +{ + if (entry->heartbeat_task) + pisa_sched_remove(&sd_ctx.scheduler, entry->heartbeat_task); +} + +/** * Initialize the basic settings before starting the main loop. */ static void sd_init(int argc, char *argv[]) @@ -200,7 +212,7 @@ conf_handle_func_set.debuglevel = pisa_conf_cb_debuglevel; conf_handle_func_set.debugmask = pisa_conf_cb_debugmask; - sd_ctx.conlist = pisa_conmgr_init(NULL); + sd_ctx.conlist = pisa_conmgr_init(pisasd_cleanup_after_removed_connection); /* create the tunnel device and assign an IP address */ inet_pton(AF_INET, "255.255.255.0", &netmask); @@ -283,8 +295,6 @@ while (sd_ctx.is_sd_running) { fd_set readfds; - pisa_sd_timeout_collect(); - /* Add all sockets to the read set */ FD_ZERO(&readfds); FD_SET(sd_ctx.tunc, &readfds); Modified: trunk/pisasd/sdregister.c ============================================================================== --- trunk/pisasd/sdregister.c Wed Oct 21 15:11:11 2009 (r1258) +++ trunk/pisasd/sdregister.c Wed Oct 21 16:15:11 2009 (r1259) @@ -14,6 +14,7 @@ #include "sdctx.h" #include "sdconf.h" #include "sdclients.h" +#include "sdheartbeat.h" #include "log.h" /** @@ -47,6 +48,7 @@ static pisa_conmgr_entry *pisa_register_client_accept(struct sockaddr_in6 *addr, uint16_t type, struct in_addr *client_ipv4) { pisa_conmgr_entry *entry; + struct timeval delay; entry = pisa_conmgr_add(sd_ctx.conlist, &addr->sin6_addr, ntohs(addr->sin6_port)); pisa_conmgr_connected(sd_ctx.conlist, entry, PISASD_DEFAULT_PORTNUM_DATA, client_ipv4); @@ -54,6 +56,12 @@ pisa_send_register_ack(entry); entry->status = PISA_CON_CONNECTED; + /* start the heartbeat task for this connection */ + entry->heartbeat_flag = 0; + delay.tv_sec = PISA_HEARTBEAT_DELAY; + delay.tv_usec = 0; + entry->heartbeat_task = pisa_sched_add(&sd_ctx.scheduler, pisa_task_heartbeat, &delay, entry); + return entry; } Modified: trunk/pisasd/sdtun.c ============================================================================== --- trunk/pisasd/sdtun.c Wed Oct 21 15:11:11 2009 (r1258) +++ trunk/pisasd/sdtun.c Wed Oct 21 16:15:11 2009 (r1259) @@ -79,7 +79,7 @@ srcaddr = (struct in_addr *)&hdr->saddr; /* Update the timeout for the connection */ - time(&entry->timeout_heartbeat); + entry->heartbeat_flag = 1; if (entry->type == PISA_CONTYPE_LEGACY_ROUTER) { map = pisa_nat_mapping_find_by_mac(sd_ctx.natlist, mac);