summaryrefslogtreecommitdiff
path: root/src/charon/sa/task_manager.h
blob: fb34aab6ace8ebf9f568baf3a5b4e3eaddb56edc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/**
 * @file task_manager.h
 * 
 * @brief Interface of task_manager_t.
 * 
 */

/*
 * Copyright (C) 2006 Martin Willi
 * Hochschule fuer Technik Rapperswil
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

#ifndef TASK_MANAGER_H_
#define TASK_MANAGER_H_

typedef struct task_manager_t task_manager_t;

#include <library.h>
#include <encoding/message.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>

/**
 * First retransmit timeout in milliseconds.
 *
 * @ingroup sa
 */
#define RETRANSMIT_TIMEOUT 4000

/**
 * Base which is raised to the power of the retransmission try.
 *
 * @ingroup sa
 */
#define RETRANSMIT_BASE 1.8

/**
 * Number of retransmits done before giving up.
 *
 * @ingroup sa
 */
#define RETRANSMIT_TRIES 5


/**
 * @brief The task manager, juggles task and handles message exchanges.
 *
 * On incoming requests, the task manager creates new tasks on demand and
 * juggles the request through all available tasks. Each task inspects the
 * request and adds payloads as necessary to the response.
 * On outgoing requests, the task manager delivers the request through the tasks
 * to build it, the response gets processed by each task to complete.
 * The task manager has an internal Queue to store task which should get
 * completed.
 * For the initial IKE_SA setup, several tasks are queued: One for the
 * unauthenticated IKE_SA setup, one for authentication, one for CHILD_SA setup
 * and maybe one for virtual IP assignement.
 * The task manager is also responsible for retransmission. It uses a backoff 
 * algorithm. The timeout is calculated using
 * RETRANSMIT_TIMEOUT * (RETRANSMIT_BASE ** try).
 * When try reaches RETRANSMIT_TRIES, retransmission is given up.
 *
 * Using an initial TIMEOUT of 4s, a BASE of 1.8, and 5 TRIES gives us:
 * @verbatim
                   | relative | absolute
   ---------------------------------------------------------
   4s * (1.8 ** 0) =    4s         4s
   4s * (1.8 ** 1) =    7s        11s
   4s * (1.8 ** 2) =   13s        24s
   4s * (1.8 ** 3) =   23s        47s
   4s * (1.8 ** 4) =   42s        89s
   4s * (1.8 ** 5) =   76s       165s
 
   @endberbatim
 * The peer is considered dead after 2min 45s when no reply comes in.
 *
 * @b Constructors:
 *  - task_manager_create()
 * 
 * @ingroup sa
 */
struct task_manager_t {

	/**
	 * @brief Process an incoming message.
	 * 
	 * @param this 			calling object
	 * @param message		message to add payloads to
	 * @return
	 * 						- DESTROY_ME if IKE_SA must be closed
	 *						- SUCCESS otherwise
	 */
	status_t (*process_message) (task_manager_t *this, message_t *message);

	/**
	 * @brief Initiate an exchange with the currently queued tasks.
	 *
	 * @param this			calling object
	 */
	status_t (*initiate) (task_manager_t *this);

	/**
	 * @brief Queue a task in the manager.
	 *
	 * @param this			calling object
	 * @param task			task to queue
	 */
	void (*queue_task) (task_manager_t *this, task_t *task);

	/**
	 * @brief Retransmit a request if it hasn't been acknowledged yet.
	 *
	 * A return value of INVALID_STATE means that the message was already
	 * acknowledged and has not to be retransmitted. A return value of SUCCESS
	 * means retransmission was required and the message has been resent.
	 * 
	 * @param this 			calling object
	 * @param message_id	ID of the message to retransmit
	 * @return
	 * 						- INVALID_STATE if retransmission not required
	 *						- SUCCESS if retransmission sent
	 */
	status_t (*retransmit) (task_manager_t *this, u_int32_t message_id);

	/**
	 * @brief Migrate all tasks from other to this.
	 *
	 * To rekey or reestablish an IKE_SA completely, all queued or active
	 * tasks should get migrated to the new IKE_SA.
	 * 
	 * @param this 			manager which gets all tasks
	 * @param other			manager which gives away its tasks
	 */
	void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
	
	/**
	 * @brief Reset message ID counters of the task manager.
	 *
	 * The IKEv2 protocol requires to restart exchanges with message IDs
	 * reset to zero (INVALID_KE_PAYLOAD, COOKIES, ...). The reset() method
	 * resets the message IDs and resets all active tasks using the migrate()
	 * method.
	 * 
	 * @param this 			calling object
	 * @param other			manager which gives away its tasks
	 */
	void (*reset) (task_manager_t *this);
	
	/**
	 * @brief Check if we are currently waiting for a reply.
	 *
	 * @param this			calling object
	 * @return				TRUE if we are waiting, FALSE otherwise
	 */
	bool (*busy) (task_manager_t *this);
	
	/**
	 * @brief Destroy the task_manager_t.
	 *
	 * @param this 			calling object
	 */
	void (*destroy) (task_manager_t *this);
};

/**
 * @brief Create an instance of the task manager.
 *
 * @param ike_sa		IKE_SA to manage.
 *
 * @ingroup sa
 */
task_manager_t *task_manager_create(ike_sa_t *ike_sa);

#endif /* TASK_MANAGER_H_ */