- retransmitting of requests implemented

This commit is contained in:
Jan Hutter 2005-12-02 14:07:36 +00:00
parent ccb37df25d
commit 0df63d6be4
12 changed files with 188 additions and 22 deletions

View 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);

View 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.
@ -104,6 +104,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_*/

View 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();

View File

@ -52,10 +52,20 @@
/**
* 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

View 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;
};
@ -65,6 +70,22 @@ static ike_sa_id_t *get_ike_sa_id(private_retransmit_request_job_t *this)
return this->ike_sa_id;
}
/**
* 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.
*/
@ -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);

View File

@ -41,6 +41,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
*

View 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,15 +198,20 @@ 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
*/
@ -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;

View File

@ -280,6 +280,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.
*

View 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 */

View 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");

View 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;

View 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);
}
/**