- retransmitting of requests implemented
authorJan Hutter <jhutter@hsr.ch>
Fri, 2 Dec 2005 14:07:36 +0000 (14:07 -0000)
committerJan Hutter <jhutter@hsr.ch>
Fri, 2 Dec 2005 14:07:36 +0000 (14:07 -0000)
12 files changed:
Source/charon/config/configuration_manager.c
Source/charon/config/configuration_manager.h
Source/charon/daemon.c
Source/charon/daemon.h
Source/charon/queues/jobs/retransmit_request_job.c
Source/charon/queues/jobs/retransmit_request_job.h
Source/charon/sa/ike_sa.c
Source/charon/sa/ike_sa.h
Source/charon/sa/states/ike_auth_requested.c
Source/charon/sa/states/ike_sa_init_requested.c
Source/charon/testcases/testcases.c
Source/charon/threads/thread_pool.c

index f3c3cd4..2f7fc09 100644 (file)
@@ -123,6 +123,17 @@ struct private_configuration_manager_t {
         * Assigned logger object.
         */
        logger_t *logger;
+       
+
+       /**
+        * Max number of retransmitted requests.
+        */     
+       u_int32_t max_retransmit_count;
+       
+       /**
+        * First retransmit timeout in ms.
+        */
+       u_int32_t first_retransmit_timeout;
 
        /**
         * Load default configuration
@@ -457,6 +468,21 @@ static void add_new_configuration (private_configuration_manager_t *this, char *
        this->configurations->insert_first(this->configurations,configuration_entry_create(name,init_config,sa_config));
 }
 
+static status_t get_retransmit_timeout (private_configuration_manager_t *this, u_int32_t retransmit_count, u_int32_t *timeout)
+{
+       if ((retransmit_count > this->max_retransmit_count) && (this->max_retransmit_count != 0))
+       {
+               return FAILED;
+       }
+       
+       /**
+        * TODO implement a good retransmit policy
+        */
+       *timeout = this->first_retransmit_timeout * (retransmit_count + 1);
+       
+       return SUCCESS;
+}
+
 /**
  * Implementation of configuration_manager_t.destroy.
  */
@@ -499,7 +525,7 @@ static void destroy(private_configuration_manager_t *this)
 /*
  * Described in header-file
  */
-configuration_manager_t *configuration_manager_create()
+configuration_manager_t *configuration_manager_create(u_int32_t first_retransmit_timeout,u_int32_t max_retransmit_count)
 {
        private_configuration_manager_t *this = allocator_alloc_thing(private_configuration_manager_t);
 
@@ -509,6 +535,7 @@ configuration_manager_t *configuration_manager_create()
        this->public.get_init_config_for_host = (status_t (*) (configuration_manager_t *, host_t *, host_t *,init_config_t **)) get_init_config_for_host;
        this->public.get_sa_config_for_name =(status_t (*) (configuration_manager_t *, char *, sa_config_t **)) get_sa_config_for_name;
        this->public.get_sa_config_for_init_config_and_id =(status_t (*) (configuration_manager_t *, init_config_t *, identification_t *, identification_t *,sa_config_t **)) get_sa_config_for_init_config_and_id;
+       this->public.get_retransmit_timeout = (status_t (*) (configuration_manager_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout;
        
        /* private functions */
        this->load_default_config = load_default_config;
@@ -519,6 +546,8 @@ configuration_manager_t *configuration_manager_create()
        this->configurations = linked_list_create();
        this->sa_configs = linked_list_create();
        this->init_configs = linked_list_create();
+       this->max_retransmit_count = max_retransmit_count;
+       this->first_retransmit_timeout = first_retransmit_timeout;
        
        this->load_default_config(this);
 
index 9cc6a31..bc6c6e8 100644 (file)
@@ -39,7 +39,7 @@ typedef struct configuration_manager_t configuration_manager_t;
 struct configuration_manager_t { 
 
        /**
-        * Gets the configuration information needed for IKE_SA_INIT exchange 
+        * Get the configuration information needed for IKE_SA_INIT exchange 
         * for a specific configuration name.
         * 
         * The returned init_config_t object MUST NOT be destroyed cause it's the original one.
@@ -55,7 +55,7 @@ struct configuration_manager_t {
        status_t (*get_init_config_for_name) (configuration_manager_t *this, char *name, init_config_t **init_config);
 
        /**
-        * Gets the configuration information needed for IKE_SA_INIT exchange 
+        * Get the configuration information needed for IKE_SA_INIT exchange 
         * for specific host informations.
         * 
         * The returned init_config_t object MUST NOT be destroyed cause it's the original one.
@@ -72,7 +72,7 @@ struct configuration_manager_t {
        status_t (*get_init_config_for_host) (configuration_manager_t *this, host_t *my_host, host_t *other_host,init_config_t **init_config);
        
        /**
-        * Gets the configuration information needed after IKE_SA_INIT exchange.
+        * Get the configuration information needed after IKE_SA_INIT exchange.
         * 
         * The returned sa_config_t object MUST not be destroyed cause it's the original one.
         * 
@@ -87,7 +87,7 @@ struct configuration_manager_t {
        status_t (*get_sa_config_for_name) (configuration_manager_t *this, char *name, sa_config_t **sa_config);
        
        /**
-        * Gets the configuration information needed after IKE_SA_INIT exchange 
+        * Get the configuration information needed after IKE_SA_INIT exchange 
         * for specific init_config_t and ID data.
         * 
         * The returned sa_config_t object MUST NOT be destroyed cause it's the original one.
@@ -105,6 +105,21 @@ struct configuration_manager_t {
        status_t (*get_sa_config_for_init_config_and_id) (configuration_manager_t *this, init_config_t *init_config, identification_t *other_id, identification_t *my_id,sa_config_t **sa_config);
 
        /**
+        * Get the retransmit timeout.
+        * 
+        * The timeout values are managed by the configuration manager.
+        * 
+        * @param this                          calling object
+        * @param retransmit_count      number of times a message was allready retransmitted
+        * @param[out] timeout          the new retransmit timeout in milliseconds
+        * 
+        * @return              
+        *                              - FAILED        if the message should not be resent again
+        *                              - SUCCESS
+        */
+       status_t (*get_retransmit_timeout) (configuration_manager_t *this, u_int32_t retransmit_count, u_int32_t *timeout);
+
+       /**
         * Destroys configuration manager
         * 
         * 
@@ -118,12 +133,14 @@ struct configuration_manager_t {
 /**
  * Creates the mighty configuration manager
  * 
+ * @param first_retransmit_timeout     first retransmit timeout in milliseconds
+ * @param max_retransmit_count         max number of retransmitted requests (0 for infinite)
  * @return 
  *                     - pointer to created manager object if succeeded
  *                     - NULL if memory allocation failed
  * 
  * @ingroup config
  */
-configuration_manager_t *configuration_manager_create();
+configuration_manager_t *configuration_manager_create(u_int32_t first_retransmit_timeout,u_int32_t max_retransmit_count);
 
 #endif /*CONFIGURATION_MANAGER_H_*/
index 7fe3d5b..d1e0c13 100644 (file)
@@ -174,7 +174,7 @@ static void initialize(private_daemon_t *this)
        this->public.job_queue = job_queue_create();
        this->public.event_queue = event_queue_create();
        this->public.send_queue = send_queue_create();
-       this->public.configuration_manager = configuration_manager_create();
+       this->public.configuration_manager = configuration_manager_create(RETRANSMIT_TIMEOUT,MAX_RETRANSMIT_COUNT);
        
        this->public.sender = sender_create();
        this->public.receiver = receiver_create();
index 8da5eb5..1b50482 100644 (file)
 
 /**
  * Port on which the daemon will 
- * listen for incoming traffic
+ * listen for incoming traffic.
  */
 #define IKEV2_UDP_PORT 4500
 
 /**
+ * First retransmit timeout in milliseconds.
+ */
+#define RETRANSMIT_TIMEOUT 3000
+
+/**
+ * Max retransmit count. 0 for infinite.
+ */
+#define MAX_RETRANSMIT_COUNT 0
+
+/**
  * Default loglevel to use. This is the
  * maximum allowed level for ever context, the definiton
  * of the context may be less verbose.
index f54de36..089ebbf 100644 (file)
@@ -46,6 +46,11 @@ struct private_retransmit_request_job_t {
         * ID of the IKE_SA which the message belongs to.
         */
        ike_sa_id_t *ike_sa_id;
+       
+       /**
+        * Number of times a request was retransmitted
+        */
+       u_int32_t retransmit_count;
 };
 
 
@@ -66,6 +71,22 @@ static ike_sa_id_t *get_ike_sa_id(private_retransmit_request_job_t *this)
 }
 
 /**
+ * Implements retransmit_request_job_t.get_retransmit_count.
+ */
+static u_int32_t get_retransmit_count(private_retransmit_request_job_t *this)
+{
+       return this->retransmit_count;
+}
+
+/**
+ * Implements retransmit_request_job_t.increase_retransmit_count.
+ */
+static void increase_retransmit_count(private_retransmit_request_job_t *this)
+{
+       this->retransmit_count++;
+}
+
+/**
  * Implements retransmit_request_job_t.get_message_id.
  */
 static u_int32_t get_message_id(private_retransmit_request_job_t *this)
@@ -100,9 +121,12 @@ retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike
        this->public.get_ike_sa_id = (ike_sa_id_t * (*)(retransmit_request_job_t *)) get_ike_sa_id;
        this->public.get_message_id = (u_int32_t (*)(retransmit_request_job_t *)) get_message_id;
        this->public.destroy = (void (*)(retransmit_request_job_t *)) destroy;
+       this->public.get_retransmit_count = (u_int32_t (*)(retransmit_request_job_t *)) get_retransmit_count;
+       this->public.increase_retransmit_count = (void (*)(retransmit_request_job_t *)) increase_retransmit_count;
        
        /* private variables */
        this->message_id = message_id;
+       this->retransmit_count = 0;
        this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
        
        return &(this->public);
index 591c798..0573f04 100644 (file)
@@ -42,6 +42,21 @@ struct retransmit_request_job_t {
        job_t job_interface;
        
        /**
+        * @brief Returns the retransmit count for a specific request.
+        *
+        * @param this  calling retransmit_request_job_t object
+        * @return              retransmit count of request
+        */
+       u_int32_t (*get_retransmit_count) (retransmit_request_job_t *this);
+
+       /**
+        * @brief Increases number of retransmitt attemps.
+        *
+        * @param this  calling retransmit_request_job_t object
+        */     
+       void (*increase_retransmit_count) (retransmit_request_job_t *this);
+       
+       /**
         * @brief Returns the message_id of the request to be resent
         *
         * @param this  calling retransmit_request_job_t object
index a974ce3..6abed04 100644 (file)
@@ -40,6 +40,7 @@
 #include <sa/states/initiator_init.h>
 #include <sa/states/responder_init.h>
 #include <queues/jobs/delete_ike_sa_job.h>
+#include <queues/jobs/retransmit_request_job.h>
 
 
 
@@ -197,16 +198,21 @@ struct private_ike_sa_t {
        } secrets;
 
        /**
-        * next message id to receive
+        * next message id to receive.
         */
        u_int32_t message_id_in;
        
        /**
-        * next message id to send
+        * next message id to send.
         */
        u_int32_t message_id_out;
        
        /**
+        * Last message id which was successfully replied.
+        */
+       u_int32_t last_replied_message_id;
+       
+       /**
         * a logger for this IKE_SA
         */
        logger_t *logger;
@@ -430,8 +436,18 @@ status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id)
        {
                return NOT_FOUND;
        }
+
+       if (message_id == this->last_replied_message_id)
+       {
+               return NOT_FOUND;
+       }
        
-       packet = this->last_responded_message->get_packet(this->last_responded_message);
+       if (this->last_requested_message == NULL)
+       {
+               return NOT_FOUND;
+       }
+       
+       packet = this->last_requested_message->get_packet(this->last_requested_message);
        charon->send_queue->add(charon->send_queue, packet);
        
        return SUCCESS;
@@ -650,6 +666,8 @@ static status_t send_request (private_ike_sa_t *this,message_t * message)
 {
        packet_t *packet;
        status_t status;
+       retransmit_request_job_t *retransmit_job;
+       u_int32_t timeout;
        
        if (message->get_message_id(message) != this->message_id_out)
        {
@@ -678,7 +696,22 @@ static status_t send_request (private_ike_sa_t *this,message_t * message)
 
        this->logger->log(this->logger, CONTROL|MOST, "replace last requested message with new one");
        this->last_requested_message = message;
-
+       
+       retransmit_job = retransmit_request_job_create(this->message_id_out,this->ike_sa_id);
+       
+       status = charon->configuration_manager->get_retransmit_timeout (charon->configuration_manager,retransmit_job->get_retransmit_count(retransmit_job),&timeout);
+       
+       if (status != SUCCESS)
+       {
+               this->logger->log(this->logger, CONTROL|MOST, "No retransmit job for message created!");
+               retransmit_job->destroy(retransmit_job);
+       }
+       else
+       {
+               this->logger->log(this->logger, CONTROL|MOST, "Request will be retransmitted in %d ms.",timeout);
+               charon->event_queue->add_relative(charon->event_queue,(job_t *) retransmit_job,timeout);
+       }
+       
        /* message counter can now be increased */
        this->logger->log(this->logger, CONTROL|MOST, "Increase message counter for outgoing messages");
        this->message_id_out++;
@@ -726,7 +759,15 @@ static status_t send_response (private_ike_sa_t *this,message_t * message)
 }
 
 /**
- * Implementation of protected_ike_sa_t.destroy.
+ * Implementation of protected_ike_sa_t.set_last_replied_message_id.
+ */
+static void set_last_replied_message_id (private_ike_sa_t *this,u_int32_t message_id)
+{
+       this->last_replied_message_id = message_id;
+}
+
+/**
+ * Implementation of protected_ike_sa_t.reset_message_buffers.
  */
 static void reset_message_buffers (private_ike_sa_t *this)
 {
@@ -747,6 +788,7 @@ static void reset_message_buffers (private_ike_sa_t *this)
        
        this->message_id_out = 0;
        this->message_id_in = 0;
+       this->last_replied_message_id = -1;
 }
 
 /**
@@ -879,7 +921,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->protected.get_crypter_responder = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_responder;
        this->protected.get_signer_responder = (signer_t *(*) (protected_ike_sa_t *)) get_signer_responder;     
        this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers;
-
+       this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id;
+       
        /* private functions */
        this->resend_last_reply = resend_last_reply;
        this->create_delete_job = create_delete_job;
@@ -897,6 +940,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->last_responded_message = NULL;
        this->message_id_out = 0;
        this->message_id_in = 0;
+       this->last_replied_message_id = -1;
        this->secrets.d_key = CHUNK_INITIALIZER;
        this->secrets.ai_key = CHUNK_INITIALIZER;
        this->secrets.ar_key = CHUNK_INITIALIZER;
index 6a12aaf..b8a897a 100644 (file)
@@ -281,6 +281,14 @@ struct protected_ike_sa_t {
        void (*set_new_state) (protected_ike_sa_t *this,state_t *state);
        
        /**
+        * Sets the last replied message id.
+        * 
+        * @param this                          calling object
+        * @param message_id            message id
+        */
+       void (*set_last_replied_message_id) (protected_ike_sa_t *this,u_int32_t message_id);
+       
+       /**
         * Gets the internal stored initiator crypter_t object.
         * 
         * @param this                          calling object
index 82d7ca9..9fe7b1b 100644 (file)
@@ -193,6 +193,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *r
                return status;
        }
 
+       this->ike_sa->set_last_replied_message_id(this->ike_sa,request->get_message_id(request));
        this->logger->log(this->logger, CONTROL | MORE, "IKE_AUTH response successfully handled. IKE_SA established.");
        
        /* create new state */
index b5ebd12..ebca25f 100644 (file)
@@ -391,6 +391,7 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t
                request->destroy(request);
                return DELETE_ME;
        }
+       this->ike_sa->set_last_replied_message_id(this->ike_sa,request->get_message_id(request));
 
        /* state can now be changed */
        this->logger->log(this->logger, CONTROL|MOST, "Create next state object");
index 28eea6e..f02d9d4 100644 (file)
@@ -142,7 +142,7 @@ daemon_t *daemon_create()
        charon->job_queue = job_queue_create();
        charon->event_queue = event_queue_create();
        charon->send_queue = send_queue_create();
-       charon->configuration_manager = configuration_manager_create();
+       charon->configuration_manager = configuration_manager_create(RETRANSMIT_TIMEOUT,MAX_RETRANSMIT_COUNT);
        charon->sender = NULL;
        charon->receiver = NULL;
        charon->scheduler = NULL;
index 649679f..87f2523 100644 (file)
@@ -153,7 +153,6 @@ static void process_jobs(private_thread_pool_t *this)
                        case RETRANSMIT_REQUEST:
                        {
                                this->process_retransmit_request_job(this, (retransmit_request_job_t*)job);
-                               job->destroy(job);
                                break;
                        }
                        default:
@@ -327,10 +326,13 @@ static void process_delete_ike_sa_job(private_thread_pool_t *this, delete_ike_sa
  */
 static void process_retransmit_request_job(private_thread_pool_t *this, retransmit_request_job_t *job)
 {
-       status_t status;
+
        ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job);
        u_int32_t message_id = job->get_message_id(job);
+       bool stop_retransmitting = FALSE;
+       u_int32_t timeout;
        ike_sa_t *ike_sa;
+       status_t status;
                                                                                
        this->worker_logger->log(this->worker_logger, CONTROL|MOST, "checking out IKE SA %lld:%lld, role %s", 
                                                         ike_sa_id->get_initiator_spi(ike_sa_id),
@@ -348,7 +350,8 @@ static void process_retransmit_request_job(private_thread_pool_t *this, retransm
                                
        if (status != SUCCESS)
        {
-               this->worker_logger->log(this->worker_logger, CONTROL | MOST, "Message does'nt have to be retransmitted");
+               this->worker_logger->log(this->worker_logger, CONTROL | MOST, "Message doesn't have to be retransmitted");
+               stop_retransmitting = TRUE;
        }
                                
        this->worker_logger->log(this->worker_logger, CONTROL|MOST, "Checkin IKE SA %lld:%lld, role %s", 
@@ -361,11 +364,25 @@ static void process_retransmit_request_job(private_thread_pool_t *this, retransm
        {
                this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!");
        }
-/*
-       u_int32_t message_id = message->get_message_id(message);
-       retransmit_request_job_t *new_job = retransmit_request_job_create(message_id,ike_sa_id);
-       charon->event_queue->add_relative(charon->event_queue,(job_t *) new_job,5000);*/
 
+       if (stop_retransmitting)
+       {
+               job->destroy(job);
+               return;
+       }
+       
+       job->increase_retransmit_count(job);
+       status = charon->configuration_manager->get_retransmit_timeout (charon->configuration_manager,job->get_retransmit_count(job),&timeout);
+       if (status != SUCCESS)
+       {
+               this->worker_logger->log(this->worker_logger, CONTROL | MOST, "Message will not be anymore retransmitted");
+               job->destroy(job);
+               /*
+                * TODO delete IKE_SA ? 
+                */
+               return;
+       }
+       charon->event_queue->add_relative(charon->event_queue,(job_t *) job,timeout);
 }
 
 /**