Author: tjansen Date: Tue Oct 27 13:43:28 2009 New Revision: 1309 Log: Callbacks in cdpending can now decide if they want to be rescheduled or if they want to be removed from the pending list. The callback functions return PISA_PENDING_DONE if they do not want to be rescheduled and PISA_PENDING_RESCHEDULE if they want to. This is useful if a send callback notices an error condition that will likely persist for the rescheduled calls as well (e.g. wrong connection status). The send callback isn't called three times in a row to notice the same error condition but is able to abort itself after the first time. Modified: trunk/pisacd/cdderegister.c trunk/pisacd/cdheartbeat.c trunk/pisacd/cdpending.c trunk/pisacd/cdpending.h trunk/pisacd/cdregister.c Modified: trunk/pisacd/cdderegister.c ============================================================================== --- trunk/pisacd/cdderegister.c Tue Oct 27 13:24:48 2009 (r1308) +++ trunk/pisacd/cdderegister.c Tue Oct 27 13:43:28 2009 (r1309) @@ -43,8 +43,10 @@ * 1. Log the attempt to disconnect from that server. * 2. Send the DEREGISTER packet. * @param pend pending request + * @return PISA_PENDING_RESCHEDULE if we want to be called again, + * PISA_PENDING_DONE otherwise */ -static void pisa_send_deregister_pend(pisa_pending *pend) +static pisa_pending_result pisa_send_deregister_pend(pisa_pending *pend) { char buffer[INET6_ADDRSTRLEN]; struct sockaddr_in6 addr = {0}; @@ -54,19 +56,23 @@ if (pend->entry->status != PISA_CON_DEREGISTERING) { PISA_DEBUG(PL_STATEMACHINE, "pisa_send_deregister_pend in a non-DEREGISTERING state.\n"); + return PISA_PENDING_DONE; } else { inet_ntop(AF_INET6, &pend->key.addr.sin6_addr, buffer, sizeof(buffer)); PISA_DEBUG(PL_DEREGISTER, "Sending DEREGISTER to %s, try %i\n", buffer, pend->count); pisa_conmgr_build_sockaddr_control(pend->entry, &addr); pisa_send_control_packet_ipv6_type(cd_ctx.tunc, &addr, PISA_PKTTYPE_TUN_DEREGISTER); + return PISA_PENDING_RESCHEDULE; } } /** * Handle a failed pending request of type DEREGISTER. * @param pend pending request + * @return PISA_PENDING_RESCHEDULE if we want to be called again, + * PISA_PENDING_DONE otherwise */ -static void pisa_send_deregister_fail(pisa_pending *pend) +static pisa_pending_result pisa_send_deregister_fail(pisa_pending *pend) { assert(pend != NULL); assert(pend->entry != NULL); @@ -76,6 +82,7 @@ } else { pisa_remove_server_connection(pend->entry); } + return PISA_PENDING_DONE; } /** Modified: trunk/pisacd/cdheartbeat.c ============================================================================== --- trunk/pisacd/cdheartbeat.c Tue Oct 27 13:24:48 2009 (r1308) +++ trunk/pisacd/cdheartbeat.c Tue Oct 27 13:43:28 2009 (r1309) @@ -43,35 +43,50 @@ /** * Handle a pending request of type HEARTBEAT. * @param pend pending request + * @return PISA_PENDING_RESCHEDULE if we want to be called again, + * PISA_PENDING_DONE otherwise */ -static void pisa_send_heartbeat_pend(pisa_pending *pend) +static pisa_pending_result pisa_send_heartbeat_pend(pisa_pending *pend) { char buffer[INET6_ADDRSTRLEN]; - pisa_conmgr_entry *entry; struct sockaddr_in6 addr = {0}; assert(pend != NULL); + assert(pend->entry != NULL); - entry = pisa_conmgr_findby_address(cd_ctx.conlist, &pend->key.addr.sin6_addr); inet_ntop(AF_INET6, &pend->key.addr.sin6_addr, buffer, sizeof(buffer)); - PISA_DEBUG(PL_HEARTBEAT, "Sending HEARTBEAT to %s, try %i\n", buffer, pend->count); - pisa_conmgr_build_sockaddr_control(entry, &addr); - pisa_send_control_packet_ipv6_type(cd_ctx.tunc, &addr, PISA_PKTTYPE_TUN_HEARTBEAT); + if (pend->entry->status == PISA_CON_CONNECTED) { + PISA_DEBUG(PL_HEARTBEAT, "Sending HEARTBEAT to %s, try %i\n", buffer, pend->count); + pisa_conmgr_build_sockaddr_control(pend->entry, &addr); + pisa_send_control_packet_ipv6_type(cd_ctx.tunc, &addr, PISA_PKTTYPE_TUN_HEARTBEAT); + return PISA_PENDING_RESCHEDULE; + } else { + PISA_DEBUG(PL_HEARTBEAT, "Skipping HEARTBEAT to %s, wrong status\n", buffer); + return PISA_PENDING_DONE; + } } /** * Handle a failed pending request of type HEARTBEAT. * @param pend pending request + * @return PISA_PENDING_RESCHEDULE if we want to be called again, + * PISA_PENDING_DONE otherwise */ -static void pisa_send_heartbeat_fail(pisa_pending *pend) +static pisa_pending_result pisa_send_heartbeat_fail(pisa_pending *pend) { char buffer[INET6_ADDRSTRLEN]; assert(pend != NULL); + assert(pend->entry != NULL); inet_ntop(AF_INET6, &pend->key.addr.sin6_addr, buffer, sizeof(buffer)); - PISA_INFO("HEARTBEAT failed to %s, disconnecting.\n", buffer); - pisa_client_disconnect_from_server(NULL, pisa_conmgr_findby_address(cd_ctx.conlist, &pend->key.addr.sin6_addr)); + if (pend->entry->status == PISA_CON_CONNECTED) { + PISA_INFO("HEARTBEAT to %s failed, disconnecting\n", buffer); + pisa_client_disconnect_from_server(NULL, pisa_conmgr_findby_address(cd_ctx.conlist, &pend->key.addr.sin6_addr)); + } else { + PISA_DEBUG(PL_HEARTBEAT, "HEARTBEAT to %s failed, wrong status\n", buffer); + } + return PISA_PENDING_DONE; } /** Modified: trunk/pisacd/cdpending.c ============================================================================== --- trunk/pisacd/cdpending.c Tue Oct 27 13:24:48 2009 (r1308) +++ trunk/pisacd/cdpending.c Tue Oct 27 13:43:28 2009 (r1309) @@ -155,7 +155,9 @@ pend->fail(pend); pisa_pending_remove(pend); } else { - pend->send(pend); - pend->task = pisa_sched_add(&cd_ctx.scheduler, pisa_task_pending, &pend->delay, pend); + if (pend->send(pend) == PISA_PENDING_RESCHEDULE) + pend->task = pisa_sched_add(&cd_ctx.scheduler, pisa_task_pending, &pend->delay, pend); + else + pisa_pending_remove(pend); } } Modified: trunk/pisacd/cdpending.h ============================================================================== --- trunk/pisacd/cdpending.h Tue Oct 27 13:24:48 2009 (r1308) +++ trunk/pisacd/cdpending.h Tue Oct 27 13:43:28 2009 (r1309) @@ -20,8 +20,13 @@ #include "scheduler.h" #include "uthash.h" +typedef enum { + PISA_PENDING_RESCHEDULE = 1, + PISA_PENDING_DONE = 2 +} pisa_pending_result; + struct pisa_pending; -typedef void (*pisa_pending_func)(struct pisa_pending *p); +typedef pisa_pending_result (*pisa_pending_func)(struct pisa_pending *p); typedef struct pisa_pending { struct { Modified: trunk/pisacd/cdregister.c ============================================================================== --- trunk/pisacd/cdregister.c Tue Oct 27 13:24:48 2009 (r1308) +++ trunk/pisacd/cdregister.c Tue Oct 27 13:43:28 2009 (r1309) @@ -23,8 +23,10 @@ * 1. Log the attempt to connect to that server. * 2. Send the REGISTER packet. * @param pend pending request + * @return PISA_PENDING_RESCHEDULE if we want to be called again, + * PISA_PENDING_DONE otherwise */ -static void pisa_send_register_pend(pisa_pending *pend) +static pisa_pending_result pisa_send_register_pend(pisa_pending *pend) { char buffer[INET6_ADDRSTRLEN]; pisa_packet *packet = pisa_alloc_msg(); @@ -35,7 +37,7 @@ if (pend->entry->status != PISA_CON_REGISTERING) { PISA_DEBUG(PL_STATEMACHINE, "pisa_send_register_pend in a non-REGISTERING state.\n"); - return; + return PISA_PENDING_DONE; } inet_ntop(AF_INET6, &pend->key.addr.sin6_addr, buffer, sizeof(buffer)); @@ -48,13 +50,16 @@ pisa_send_control_packet_ipv6(cd_ctx.tunc, &pend->key.addr, packet); pisa_free_msg(packet); + return PISA_PENDING_RESCHEDULE; } /** * Handle a failed pending request of type REGISTER. * @param pend pending request + * @return PISA_PENDING_RESCHEDULE if we want to be called again, + * PISA_PENDING_DONE otherwise */ -static void pisa_send_register_fail(pisa_pending *pend) +static pisa_pending_result pisa_send_register_fail(pisa_pending *pend) { char buffer[INET6_ADDRSTRLEN]; @@ -68,6 +73,7 @@ PISA_DEBUG(PL_REGISTER, "Failed to REGISTER to %s.\n", buffer); pend->entry->status = PISA_CON_DISCONNECTED; } + return PISA_PENDING_DONE; } /**