2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <osip2/internal.h>
21 #include <osip2/osip.h>
25 osip_statemachine_t *nist_fsm;
36 transition_t *transition;
37 osip_statemachine_t *statemachine = __nist_get_fsm ();
39 while (!osip_list_eol (statemachine->transitions, 0))
42 (transition_t *) osip_list_get (statemachine->transitions, 0);
43 osip_list_remove (statemachine->transitions, 0);
44 osip_free (transition);
46 osip_free (statemachine->transitions);
47 osip_free (statemachine);
54 transition_t *transition;
57 (osip_statemachine_t *) osip_malloc (sizeof (osip_statemachine_t));
58 nist_fsm->transitions = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
59 osip_list_init (nist_fsm->transitions);
61 transition = (transition_t *) osip_malloc (sizeof (transition_t));
62 transition->state = NIST_PRE_TRYING;
63 transition->type = RCV_REQUEST;
64 transition->method = (void (*)(void *, void *)) &nist_rcv_request;
65 osip_list_add (nist_fsm->transitions, transition, -1);
67 /* This can be used to announce request but is useless, as
68 the transaction cannot send any response yet!
69 transition = (transition_t *) osip_malloc(sizeof(transition_t));
70 transition->state = NIST_TRYING;
71 transition->type = RCV_REQUEST;
72 transition->method = (void(*)(void *,void *))&nist_rcv_request;
73 osip_list_add(nist_fsm->transitions,transition,-1);
76 transition = (transition_t *) osip_malloc (sizeof (transition_t));
77 transition->state = NIST_TRYING;
78 transition->type = SND_STATUS_1XX;
79 transition->method = (void (*)(void *, void *)) &nist_snd_1xx;
80 osip_list_add (nist_fsm->transitions, transition, -1);
82 transition = (transition_t *) osip_malloc (sizeof (transition_t));
83 transition->state = NIST_TRYING;
84 transition->type = SND_STATUS_2XX;
85 transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
86 osip_list_add (nist_fsm->transitions, transition, -1);
88 transition = (transition_t *) osip_malloc (sizeof (transition_t));
89 transition->state = NIST_TRYING;
90 transition->type = SND_STATUS_3456XX;
91 transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
92 osip_list_add (nist_fsm->transitions, transition, -1);
94 transition = (transition_t *) osip_malloc (sizeof (transition_t));
95 transition->state = NIST_PROCEEDING;
96 transition->type = SND_STATUS_1XX;
97 transition->method = (void (*)(void *, void *)) &nist_snd_1xx;
98 osip_list_add (nist_fsm->transitions, transition, -1);
100 transition = (transition_t *) osip_malloc (sizeof (transition_t));
101 transition->state = NIST_PROCEEDING;
102 transition->type = SND_STATUS_2XX;
103 transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
104 osip_list_add (nist_fsm->transitions, transition, -1);
106 transition = (transition_t *) osip_malloc (sizeof (transition_t));
107 transition->state = NIST_PROCEEDING;
108 transition->type = SND_STATUS_3456XX;
109 transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
110 osip_list_add (nist_fsm->transitions, transition, -1);
112 transition = (transition_t *) osip_malloc (sizeof (transition_t));
113 transition->state = NIST_PROCEEDING;
114 transition->type = RCV_REQUEST;
115 transition->method = (void (*)(void *, void *)) &nist_rcv_request;
116 osip_list_add (nist_fsm->transitions, transition, -1);
118 transition = (transition_t *) osip_malloc (sizeof (transition_t));
119 transition->state = NIST_COMPLETED;
120 transition->type = TIMEOUT_J;
121 transition->method = (void (*)(void *, void *)) &osip_nist_timeout_j_event;
122 osip_list_add (nist_fsm->transitions, transition, -1);
124 transition = (transition_t *) osip_malloc (sizeof (transition_t));
125 transition->state = NIST_COMPLETED;
126 transition->type = RCV_REQUEST;
127 transition->method = (void (*)(void *, void *)) &nist_rcv_request;
128 osip_list_add (nist_fsm->transitions, transition, -1);
133 nist_handle_transport_error (osip_transaction_t * nist, int err)
135 __osip_transport_error_callback (OSIP_NIST_TRANSPORT_ERROR, nist, err);
136 __osip_transaction_set_state (nist, NIST_TERMINATED);
137 __osip_kill_transaction_callback (OSIP_NIST_KILL_TRANSACTION, nist);
138 /* TODO: MUST BE DELETED NOW */
142 nist_rcv_request (osip_transaction_t * nist, osip_event_t * evt)
145 osip_t *osip = (osip_t *) nist->config;
147 if (nist->state == NIST_PRE_TRYING) /* announce new REQUEST */
149 /* Here we have ist->orig_request == NULL */
150 nist->orig_request = evt->sip;
152 if (MSG_IS_REGISTER (evt->sip))
153 __osip_message_callback (OSIP_NIST_REGISTER_RECEIVED, nist,
155 else if (MSG_IS_BYE (evt->sip))
156 __osip_message_callback (OSIP_NIST_BYE_RECEIVED, nist,
158 else if (MSG_IS_OPTIONS (evt->sip))
159 __osip_message_callback (OSIP_NIST_OPTIONS_RECEIVED, nist,
161 else if (MSG_IS_INFO (evt->sip))
162 __osip_message_callback (OSIP_NIST_INFO_RECEIVED, nist,
164 else if (MSG_IS_CANCEL (evt->sip))
165 __osip_message_callback (OSIP_NIST_CANCEL_RECEIVED, nist,
167 else if (MSG_IS_NOTIFY (evt->sip))
168 __osip_message_callback (OSIP_NIST_NOTIFY_RECEIVED, nist,
170 else if (MSG_IS_SUBSCRIBE (evt->sip))
171 __osip_message_callback (OSIP_NIST_SUBSCRIBE_RECEIVED, nist,
174 __osip_message_callback (OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, nist,
177 else /* NIST_PROCEEDING or NIST_COMPLETED */
179 /* delete retransmission */
180 osip_message_free (evt->sip);
182 __osip_message_callback (OSIP_NIST_REQUEST_RECEIVED_AGAIN, nist,
184 if (nist->last_response != NULL) /* retransmit last response */
188 via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
193 osip_generic_param_t *maddr;
194 osip_generic_param_t *received;
195 osip_generic_param_t *rport;
196 osip_via_param_get_byname (via, "maddr", &maddr);
197 osip_via_param_get_byname (via, "received", &received);
198 osip_via_param_get_byname (via, "rport", &rport);
199 /* 1: user should not use the provided information
200 (host and port) if they are using a reliable
201 transport. Instead, they should use the already
202 open socket attached to this transaction. */
203 /* 2: check maddr and multicast usage */
205 host = maddr->gvalue;
206 /* we should check if this is a multicast address and use
207 set the "ttl" in this case. (this must be done in the
208 UDP message (not at the SIP layer) */
209 else if (received != NULL)
210 host = received->gvalue;
214 if (rport == NULL || rport->gvalue == NULL)
216 if (via->port != NULL)
217 port = osip_atoi (via->port);
222 port = osip_atoi (rport->gvalue);
224 i = osip->cb_send_message (nist, nist->last_response, host,
225 port, nist->out_socket);
231 nist_handle_transport_error (nist, i);
236 if (MSG_IS_STATUS_1XX (nist->last_response))
237 __osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist,
238 nist->last_response);
239 else if (MSG_IS_STATUS_2XX (nist->last_response))
240 __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT_AGAIN,
241 nist, nist->last_response);
243 __osip_message_callback (OSIP_NIST_STATUS_3456XX_SENT_AGAIN,
244 nist, nist->last_response);
248 /* we are already in the proper state */
252 /* we come here only if it was the first REQUEST received */
253 __osip_transaction_set_state (nist, NIST_TRYING);
257 nist_snd_1xx (osip_transaction_t * nist, osip_event_t * evt)
261 osip_t *osip = (osip_t *) nist->config;
263 if (nist->last_response != NULL)
265 osip_message_free (nist->last_response);
267 nist->last_response = evt->sip;
269 via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
274 osip_generic_param_t *maddr;
275 osip_generic_param_t *received;
276 osip_generic_param_t *rport;
277 osip_via_param_get_byname (via, "maddr", &maddr);
278 osip_via_param_get_byname (via, "received", &received);
279 osip_via_param_get_byname (via, "rport", &rport);
280 /* 1: user should not use the provided information
281 (host and port) if they are using a reliable
282 transport. Instead, they should use the already
283 open socket attached to this transaction. */
284 /* 2: check maddr and multicast usage */
286 host = maddr->gvalue;
287 /* we should check if this is a multicast address and use
288 set the "ttl" in this case. (this must be done in the
289 UDP message (not at the SIP layer) */
290 else if (received != NULL)
291 host = received->gvalue;
295 if (rport == NULL || rport->gvalue == NULL)
297 if (via->port != NULL)
298 port = osip_atoi (via->port);
303 port = osip_atoi (rport->gvalue);
304 i = osip->cb_send_message (nist, nist->last_response, host,
305 port, nist->out_socket);
311 nist_handle_transport_error (nist, i);
315 __osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist,
316 nist->last_response);
318 __osip_transaction_set_state (nist, NIST_PROCEEDING);
322 nist_snd_23456xx (osip_transaction_t * nist, osip_event_t * evt)
326 osip_t *osip = (osip_t *) nist->config;
328 if (nist->last_response != NULL)
330 osip_message_free (nist->last_response);
332 nist->last_response = evt->sip;
334 via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
339 osip_generic_param_t *maddr;
340 osip_generic_param_t *received;
341 osip_generic_param_t *rport;
342 osip_via_param_get_byname (via, "maddr", &maddr);
343 osip_via_param_get_byname (via, "received", &received);
344 osip_via_param_get_byname (via, "rport", &rport);
345 /* 1: user should not use the provided information
346 (host and port) if they are using a reliable
347 transport. Instead, they should use the already
348 open socket attached to this transaction. */
349 /* 2: check maddr and multicast usage */
351 host = maddr->gvalue;
352 /* we should check if this is a multicast address and use
353 set the "ttl" in this case. (this must be done in the
354 UDP message (not at the SIP layer) */
355 else if (received != NULL)
356 host = received->gvalue;
360 if (rport == NULL || rport->gvalue == NULL)
362 if (via->port != NULL)
363 port = osip_atoi (via->port);
368 port = osip_atoi (rport->gvalue);
369 i = osip->cb_send_message (nist, nist->last_response, host,
370 port, nist->out_socket);
376 nist_handle_transport_error (nist, i);
381 if (EVT_IS_SND_STATUS_2XX (evt))
382 __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT, nist,
383 nist->last_response);
384 else if (MSG_IS_STATUS_3XX (nist->last_response))
385 __osip_message_callback (OSIP_NIST_STATUS_3XX_SENT, nist,
386 nist->last_response);
387 else if (MSG_IS_STATUS_4XX (nist->last_response))
388 __osip_message_callback (OSIP_NIST_STATUS_4XX_SENT, nist,
389 nist->last_response);
390 else if (MSG_IS_STATUS_5XX (nist->last_response))
391 __osip_message_callback (OSIP_NIST_STATUS_5XX_SENT, nist,
392 nist->last_response);
394 __osip_message_callback (OSIP_NIST_STATUS_6XX_SENT, nist,
395 nist->last_response);
398 if (nist->state != NIST_COMPLETED) /* start J timer */
400 gettimeofday (&nist->nist_context->timer_j_start, NULL);
401 add_gettimeofday (&nist->nist_context->timer_j_start,
402 nist->nist_context->timer_j_length);
405 __osip_transaction_set_state (nist, NIST_COMPLETED);
410 osip_nist_timeout_j_event (osip_transaction_t * nist, osip_event_t * evt)
412 nist->nist_context->timer_j_length = -1;
413 nist->nist_context->timer_j_start.tv_sec = -1;
415 __osip_transaction_set_state (nist, NIST_TERMINATED);
416 __osip_kill_transaction_callback (OSIP_NIST_KILL_TRANSACTION, nist);