Mercurial > hg > freeDiameter
comparison freeDiameter/p_psm.c @ 33:e6fcdf12b9a0
Added a lot of TODOs :)
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 29 Oct 2009 18:05:45 +0900 |
parents | 5ba91682f0bc |
children | 0e2b57789361 |
comparison
equal
deleted
inserted
replaced
32:a5b507479a09 | 33:e6fcdf12b9a0 |
---|---|
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * | 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * |
34 *********************************************************************************************************/ | 34 *********************************************************************************************************/ |
35 | 35 |
36 #include "fD.h" | 36 #include "fD.h" |
37 | 37 |
38 const char *peer_state_str[] = { | 38 /* The actual declaration of peer_state_str */ |
39 "STATE_NEW" | 39 DECLARE_STATE_STR(); |
40 , "STATE_OPEN" | 40 |
41 , "STATE_CLOSED" | 41 /* Helper for next macro */ |
42 , "STATE_CLOSING" | 42 #define case_str( _val ) \ |
43 , "STATE_WAITCNXACK" | 43 case _val : return #_val |
44 , "STATE_WAITCNXACK_ELEC" | 44 |
45 , "STATE_WAITCEA" | 45 DECLARE_PEV_STR(); |
46 , "STATE_OPEN_HANDSHAKE" | 46 |
47 , "STATE_SUSPECT" | 47 /************************************************************************/ |
48 , "STATE_REOPEN" | 48 /* Delayed startup */ |
49 , "STATE_ZOMBIE" | 49 /************************************************************************/ |
50 }; | |
51 | |
52 const char * fd_pev_str(int event) | |
53 { | |
54 switch (event) { | |
55 #define case_str( _val )\ | |
56 case _val : return #_val | |
57 case_str(FDEVP_DUMP_ALL); | |
58 case_str(FDEVP_TERMINATE); | |
59 case_str(FDEVP_CNX_MSG_RECV); | |
60 case_str(FDEVP_CNX_ERROR); | |
61 case_str(FDEVP_CNX_EP_CHANGE); | |
62 case_str(FDEVP_CNX_INCOMING); | |
63 case_str(FDEVP_PSM_TIMEOUT); | |
64 | |
65 default: | |
66 TRACE_DEBUG(FULL, "Unknown event : %d", event); | |
67 return "Unknown event"; | |
68 } | |
69 } | |
70 | |
71 | |
72 static int started = 0; | 50 static int started = 0; |
73 static pthread_mutex_t started_mtx = PTHREAD_MUTEX_INITIALIZER; | 51 static pthread_mutex_t started_mtx = PTHREAD_MUTEX_INITIALIZER; |
74 static pthread_cond_t started_cnd = PTHREAD_COND_INITIALIZER; | 52 static pthread_cond_t started_cnd = PTHREAD_COND_INITIALIZER; |
75 | 53 |
76 /* Wait for start signal */ | 54 /* Wait for start signal */ |
87 } | 65 } |
88 CHECK_POSIX( pthread_mutex_unlock(&started_mtx) ); | 66 CHECK_POSIX( pthread_mutex_unlock(&started_mtx) ); |
89 return 0; | 67 return 0; |
90 } | 68 } |
91 | 69 |
92 /* Cancelation cleanup : set ZOMBIE state in the peer */ | 70 /* Allow the state machines to start */ |
93 void cleanup_state(void * arg) | 71 int fd_psm_start() |
94 { | 72 { |
95 struct fd_peer * peer = (struct fd_peer *)arg; | 73 TRACE_ENTRY(""); |
96 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); | 74 CHECK_POSIX( pthread_mutex_lock(&started_mtx) ); |
97 peer->p_hdr.info.pi_state = STATE_ZOMBIE; | 75 started = 1; |
98 return; | 76 CHECK_POSIX( pthread_cond_broadcast(&started_cnd) ); |
77 CHECK_POSIX( pthread_mutex_unlock(&started_mtx) ); | |
78 return 0; | |
79 } | |
80 | |
81 | |
82 /************************************************************************/ | |
83 /* Manage the list of active peers */ | |
84 /************************************************************************/ | |
85 | |
86 | |
87 /* Enter/leave OPEN state */ | |
88 static int enter_open_state(struct fd_peer * peer) | |
89 { | |
90 CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) ); | |
91 TODO(" insert in fd_g_activ_peers "); | |
92 | |
93 CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) ); | |
94 | |
95 /* Start the thread to handle outgoing messages */ | |
96 CHECK_FCT( fd_out_start(peer) ); | |
97 | |
98 return ENOTSUP; | |
99 } | |
100 static int leave_open_state(struct fd_peer * peer) | |
101 { | |
102 TODO("Remove from active list"); | |
103 | |
104 /* Stop the "out" thread */ | |
105 CHECK_FCT( fd_out_stop(peer) ); | |
106 | |
107 TODO("Failover pending messages: requeue in global structures"); | |
108 | |
109 return ENOTSUP; | |
110 } | |
111 | |
112 /************************************************************************/ | |
113 /* Helpers for state changes */ | |
114 /************************************************************************/ | |
115 /* Change state */ | |
116 static int change_state(struct fd_peer * peer, int new_state) | |
117 { | |
118 int old; | |
119 | |
120 TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state)); | |
121 CHECK_PARAMS( CHECK_PEER(peer) ); | |
122 old = peer->p_hdr.info.pi_state; | |
123 if (old == new_state) | |
124 return 0; | |
125 | |
126 TRACE_DEBUG(FULL, "'%s'\t-> '%s'\t'%s'", | |
127 STATE_STR(old), | |
128 STATE_STR(new_state), | |
129 peer->p_hdr.info.pi_diamid); | |
130 | |
131 if (old == STATE_OPEN) { | |
132 CHECK_FCT( leave_open_state(peer) ); | |
133 } | |
134 | |
135 peer->p_hdr.info.pi_state = new_state; | |
136 | |
137 if (new_state == STATE_OPEN) { | |
138 CHECK_FCT( enter_open_state(peer) ); | |
139 } | |
140 | |
141 return 0; | |
99 } | 142 } |
100 | 143 |
101 /* Set timeout timer of next event */ | 144 /* Set timeout timer of next event */ |
102 static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay) | 145 static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay) |
103 { | 146 { |
125 /* temporary for debug */ | 168 /* temporary for debug */ |
126 peer->p_psm_timer.tv_sec += 10; | 169 peer->p_psm_timer.tv_sec += 10; |
127 #endif | 170 #endif |
128 } | 171 } |
129 | 172 |
173 | |
174 /************************************************************************/ | |
175 /* The PSM thread */ | |
176 /************************************************************************/ | |
177 /* Cancelation cleanup : set ZOMBIE state in the peer */ | |
178 void cleanup_state(void * arg) | |
179 { | |
180 struct fd_peer * peer = (struct fd_peer *)arg; | |
181 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); | |
182 peer->p_hdr.info.pi_state = STATE_ZOMBIE; | |
183 return; | |
184 } | |
185 | |
130 /* The state machine thread (controler) */ | 186 /* The state machine thread (controler) */ |
131 static void * p_psm_th( void * arg ) | 187 static void * p_psm_th( void * arg ) |
132 { | 188 { |
133 struct fd_peer * peer = (struct fd_peer *)arg; | 189 struct fd_peer * peer = (struct fd_peer *)arg; |
134 int created_started = started; | 190 int created_started = started; |
168 fd_pev_str(event), ev_data, ev_sz, | 224 fd_pev_str(event), ev_data, ev_sz, |
169 peer->p_hdr.info.pi_diamid); | 225 peer->p_hdr.info.pi_diamid); |
170 | 226 |
171 /* Now, the action depends on the current state and the incoming event */ | 227 /* Now, the action depends on the current state and the incoming event */ |
172 | 228 |
173 /* The following two states are impossible */ | 229 /* The following states are impossible */ |
174 ASSERT( peer->p_hdr.info.pi_state != STATE_NEW ); | 230 ASSERT( peer->p_hdr.info.pi_state != STATE_NEW ); |
175 ASSERT( peer->p_hdr.info.pi_state != STATE_ZOMBIE ); | 231 ASSERT( peer->p_hdr.info.pi_state != STATE_ZOMBIE ); |
232 ASSERT( peer->p_hdr.info.pi_state != STATE_OPEN_HANDSHAKE ); /* because it exists only between two loops */ | |
176 | 233 |
177 /* Purge invalid events */ | 234 /* Purge invalid events */ |
178 if (!CHECK_EVENT(event)) { | 235 if (!CHECK_PEVENT(event)) { |
179 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); | 236 TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event); |
180 goto psm_loop; | 237 goto psm_loop; |
238 } | |
239 | |
240 /* Call the extension callback if needed */ | |
241 if (peer->p_cb) { | |
242 /* Check if we must call it */ | |
243 /* */ | |
244 /* OK */ | |
245 TODO("Call CB"); | |
246 TODO("Clear CB"); | |
181 } | 247 } |
182 | 248 |
183 /* Handle the (easy) debug event now */ | 249 /* Handle the (easy) debug event now */ |
184 if (event == FDEVP_DUMP_ALL) { | 250 if (event == FDEVP_DUMP_ALL) { |
185 fd_peer_dump(peer, ANNOYING); | 251 fd_peer_dump(peer, ANNOYING); |
204 case STATE_REOPEN: | 270 case STATE_REOPEN: |
205 /* We cannot just close the conenction, we have to send a DPR first */ | 271 /* We cannot just close the conenction, we have to send a DPR first */ |
206 TODO("Send DPR, mark the peer as CLOSING"); | 272 TODO("Send DPR, mark the peer as CLOSING"); |
207 goto psm_loop; | 273 goto psm_loop; |
208 } | 274 } |
275 } | |
276 | |
277 /* A message was received */ | |
278 if (event == FDEVP_CNX_MSG_RECV) { | |
279 TODO("Parse the buffer into a message"); | |
280 /* parse_and_get_local_ccode */ | |
281 TODO("Check if it is a local message (CER, DWR, ...)"); | |
282 TODO("If not, check we are in OPEN state"); | |
283 TODO("Update expiry timer if needed"); | |
284 TODO("Handle the message"); | |
285 } | |
286 | |
287 /* The connection object is broken */ | |
288 if (event == FDEVP_CNX_ERROR) { | |
289 TODO("Destroy the connection object"); | |
290 TODO("Mark the error in the peer (pf_cnx_pb)"); | |
291 TODO("Move to closed state, Requeue all messages to a different connection (failover)"); | |
292 TODO("If pi_flags.exp, terminate the peer"); | |
293 } | |
294 | |
295 /* The connection notified a change in endpoints */ | |
296 if (event == FDEVP_CNX_EP_CHANGE) { | |
297 /* Cleanup the remote LL and primary addresses */ | |
298 CHECK_FCT_DO( fd_ep_filter( &peer->p_hdr.info.pi_endpoints, EP_FL_CONF | EP_FL_DISC | EP_FL_ADV ), /* ignore the error */); | |
299 CHECK_FCT_DO( fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_PRIMARY ), /* ignore the error */); | |
300 | |
301 /* Get the new ones */ | |
302 CHECK_FCT_DO( fd_cnx_getendpoints(peer->p_cnxctx, NULL, &peer->p_hdr.info.pi_endpoints), /* ignore the error */); | |
303 | |
304 if (TRACE_BOOL(ANNOYING)) { | |
305 fd_log_debug("New remote endpoint(s):\n"); | |
306 fd_ep_dump(6, &peer->p_hdr.info.pi_endpoints); | |
307 } | |
308 | |
309 /* Done */ | |
310 goto psm_loop; | |
209 } | 311 } |
210 | 312 |
211 /* A new connection was established and CER containing this peer id was received */ | 313 /* A new connection was established and CER containing this peer id was received */ |
212 if (event == FDEVP_CNX_INCOMING) { | 314 if (event == FDEVP_CNX_INCOMING) { |
213 struct cnx_incoming * params = ev_data; | 315 struct cnx_incoming * params = ev_data; |
232 | 334 |
233 free(ev_data); | 335 free(ev_data); |
234 goto psm_loop; | 336 goto psm_loop; |
235 } | 337 } |
236 | 338 |
237 /* MSG_RECEIVED: fd_p_expi_update(struct fd_peer * peer ) */ | 339 /* The timeout for the current state has been reached */ |
238 /* If timeout or OPEN : call cb if defined */ | 340 if (event == FDEVP_PSM_TIMEOUT) { |
239 | 341 switch (peer->p_hdr.info.pi_state) { |
240 /* Default action : the handling has not yet been implemented. */ | 342 |
343 | |
344 } | |
345 } | |
346 | |
347 /* Default action : the handling has not yet been implemented. [for debug only] */ | |
241 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event)); | 348 TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event)); |
242 if (event == FDEVP_PSM_TIMEOUT) { | 349 if (event == FDEVP_PSM_TIMEOUT) { |
243 /* We have not handled timeout in this state, let's postpone next alert */ | 350 /* We have not handled timeout in this state, let's postpone next alert */ |
244 psm_next_timeout(peer, 0, 60); | 351 psm_next_timeout(peer, 0, 60); |
245 } | 352 } |
249 psm_end: | 356 psm_end: |
250 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ | 357 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ |
251 peer->p_psm = (pthread_t)NULL; | 358 peer->p_psm = (pthread_t)NULL; |
252 pthread_detach(pthread_self()); | 359 pthread_detach(pthread_self()); |
253 return NULL; | 360 return NULL; |
254 } | 361 } |
255 | 362 |
363 | |
364 /************************************************************************/ | |
365 /* Functions to control the PSM */ | |
366 /************************************************************************/ | |
256 /* Create the PSM thread of one peer structure */ | 367 /* Create the PSM thread of one peer structure */ |
257 int fd_psm_begin(struct fd_peer * peer ) | 368 int fd_psm_begin(struct fd_peer * peer ) |
258 { | 369 { |
259 TRACE_ENTRY("%p", peer); | 370 TRACE_ENTRY("%p", peer); |
260 | 371 |
280 TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid); | 391 TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid); |
281 } | 392 } |
282 return 0; | 393 return 0; |
283 } | 394 } |
284 | 395 |
285 /* End the PSM violently */ | 396 /* End the PSM & cleanup the peer structure */ |
286 void fd_psm_abord(struct fd_peer * peer ) | 397 void fd_psm_abord(struct fd_peer * peer ) |
287 { | 398 { |
288 TRACE_ENTRY("%p", peer); | 399 TRACE_ENTRY("%p", peer); |
289 TODO("Cancel PSM thread"); | 400 TODO("Cancel PSM thread"); |
290 TODO("Cancel IN thread"); | |
291 TODO("Cancel OUT thread"); | 401 TODO("Cancel OUT thread"); |
292 TODO("Cleanup the peer connection object"); | 402 TODO("Cleanup the peer connection object"); |
293 TODO("Cleanup the message queues (requeue)"); | 403 TODO("Cleanup the message queues (requeue)"); |
404 TODO("Call p_cb with NULL parameter if needed"); | |
405 | |
294 return; | 406 return; |
295 } | 407 } |
296 | 408 |
297 /* Allow the state machines to start */ | |
298 int fd_psm_start() | |
299 { | |
300 TRACE_ENTRY(""); | |
301 CHECK_POSIX( pthread_mutex_lock(&started_mtx) ); | |
302 started = 1; | |
303 CHECK_POSIX( pthread_cond_broadcast(&started_cnd) ); | |
304 CHECK_POSIX( pthread_mutex_unlock(&started_mtx) ); | |
305 return 0; | |
306 } | |
307 |