fa623e4510d34400c677954bac9687fe13aa1d34
[sip-router] / modules / tm / t_reply.c
1 /*
2  * $Id$
3  *
4  */
5
6
7 #include "hash_func.h"
8 #include "t_funcs.h"
9 #include "../../dprint.h"
10 #include "../../config.h"
11 #include "../../parser/parser_f.h"
12 #include "../../ut.h"
13 #include "../../timer.h"
14
15 #include "t_hooks.h"
16
17
18
19
20 inline int check_for_no_response( struct cell *Trans ,int code, int relay)
21 {
22         if ( code/100>3 && Trans->uac[Trans->nr_of_outgoings].uri.s )
23         {
24                 forward_serial_branch( Trans , Trans->nr_of_outgoings );
25                 return -1;
26         }
27         return relay;
28 }
29
30
31
32 /* Retransmits the last sent inbound reply.
33  * input: p_msg==request for which I want to retransmit an associated reply
34  * Returns  -1 - error
35  *           1 - OK
36  */
37 int t_retransmit_reply( /* struct sip_msg* p_msg    */ )
38 {
39         static char b[BUF_SIZE];
40         int len;
41
42         if (!T->uas.response.buffer)
43                 return -1;
44
45         if ( (len=T->uas.response.buffer_len)==0 || len>BUF_SIZE ) {
46                 UNLOCK_REPLIES( T );
47                 return -2;
48         }
49         memcpy( b, T->uas.response.buffer, len );
50         UNLOCK_REPLIES( T );
51         SEND_PR_BUFFER( & T->uas.response, b, len );
52         return 1;
53 }
54
55
56
57
58
59 /* Force a new response into inbound response buffer.
60   * returns 1 if everything was OK or -1 for error
61   */
62 int t_send_reply( struct sip_msg* p_msg, unsigned int code, char * text,
63                                                                                                                 unsigned int branch)
64 {
65         unsigned int len, buf_len=0;
66         char * buf;
67         struct retr_buf *rb;
68         int relay, save_clone;
69
70         buf = build_res_buf_from_sip_req(code,text,T->uas.tag->s,T->uas.tag->len,
71                 T->uas.request,&len);
72         DBG("DEBUG: t_send_reply: buffer computed\n");
73         if (!buf)
74         {
75                 DBG("DEBUG: t_send_reply: response building failed\n");
76                 goto error;
77         }
78
79         LOCK_REPLIES( T );
80         relay = t_should_relay_response(T, code, branch, &save_clone);
81
82         if (save_clone)
83         {
84                 T->uac[branch].status = code;
85         }
86
87         rb = & T->uas.response;
88         if (relay >=0 && (relay=check_for_no_response(T,code,relay))>=0 )
89         {
90                 if (!rb->buffer) {
91                         /* initialize retransmission structure */
92                         if (update_sock_struct_from_via(  &(rb->to),  p_msg->via1 )==-1)
93                         {
94                                 UNLOCK_REPLIES( T );
95                                 LOG(L_ERR,"ERROR: t_send_reply: cannot lookup reply dst: %s\n",
96                                         p_msg->via1->host.s );
97                                 goto error2;
98                         }
99                         rb->to.sin_family = AF_INET;
100                         rb->activ_type = code;
101                         buf_len = len + REPLY_OVERBUFFER_LEN;
102                 }else{
103                         buf_len = len;
104                 }
105                 /* puts the reply's buffer to uas.response */
106                 if (! (rb->buffer = (char*)shm_resize( rb->buffer, buf_len )))
107                 {
108                         UNLOCK_REPLIES( T );
109                         LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem buffer\n");
110                         goto error2;
111                 }
112                 rb->buffer_len = len ;
113                 memcpy( rb->buffer , buf , len );
114                 T->uas.status = code;
115                 /* needs to be protected too because what timers are set depends
116                    on current transactions status */
117                 t_update_timers_after_sending_reply( rb );
118         } /* if realy */
119
120         UNLOCK_REPLIES( T );
121
122         if (relay>=0) SEND_PR_BUFFER( rb, buf, len );
123         pkg_free( buf ) ;
124         DBG("DEBUG: t_send_reply: finished\n");
125         return 1;
126
127 error2:
128         pkg_free ( buf );
129 error:
130         return -1;
131 }
132
133
134
135 #if 0
136 /* Push a previously stored reply from UA Client to UA Server
137  * and send it out */
138 static int push_reply( struct cell* trans , unsigned int branch ,
139                                                                                                 char *buf, unsigned int len)
140 {
141         unsigned int buf_len;
142         struct retrans_buff *rb;
143
144         DBG("DEBUG: push_reply_from_uac_to_uas: start\n");
145         rb= & trans->outbound_response;
146         /* if there is a reply, release the buffer (everything else stays same) */
147         if ( ! rb->retr_buffer ) {
148                 /*init retrans buffer*/
149                 memset( rb , 0 , sizeof (struct retrans_buff) );
150                 if (update_sock_struct_from_via(  &(rb->to),
151                         trans->inbound_response[branch]->via2 )==-1) {
152                                 LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: "
153                                         "cannot lookup reply dst: %s\n",
154                                 trans->inbound_response[branch]->via2->host.s );
155                                 goto error;
156                 }
157                 rb->retr_timer.tg=TG_RT;
158                 rb->fr_timer.tg=TG_FR;
159                 rb->retr_timer.payload = rb;
160                 rb->fr_timer.payload =  rb;
161                 rb->to.sin_family = AF_INET;
162                 rb->my_T = trans;
163                 rb->status = trans->inbound_response[branch]->REPLY_STATUS;
164         };
165
166         /* if this is a first reply (?100), longer replies will probably follow;
167         try avoiding shm_resize by higher buffer size */
168         buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN;
169         if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len )))
170         {
171                 LOG(L_ERR, "ERROR: t_push: cannot allocate shmem buffer\n");
172                 goto error1;
173         }
174         rb->bufflen = len ;
175         memcpy( rb->retr_buffer , buf , len );
176
177         /* update the status*/
178         trans->status = trans->inbound_response[branch]->REPLY_STATUS;
179         if ( trans->inbound_response[branch]->REPLY_STATUS>=200 &&
180                 trans->relaied_reply_branch==-1 ) {
181
182                 memcpy( & trans->ack_to, & trans->outbound_request[ branch ]->to,
183                         sizeof( struct sockaddr_in ) );
184                 trans->relaied_reply_branch = branch;
185         }
186
187         /*send the reply*/
188         SEND_BUFFER( rb );
189         return 1;
190
191 error1:
192 error:
193         return -1;
194 }
195 #endif
196
197
198
199 /*  This function is called whenever a reply for our module is received; 
200   * we need to register  this function on module initialization;
201   *  Returns :   0 - core router stops
202   *              1 - core router relay statelessly
203   */
204 int t_on_reply( struct sip_msg  *p_msg )
205 {
206         int branch, msg_status, msg_class, save_clone;
207         int local_cancel;
208         int relay;
209         int start_fr = 0;
210         int is_invite;
211         /* retransmission structure of outbound reply and request */
212         struct retr_buf *rb=0;
213         char *buf=0, *ack=0;
214         /* length of outbound reply */
215         unsigned int res_len, ack_len;
216         /* buffer length (might be somewhat larger than message size */
217         unsigned int alloc_len;
218         str *str_foo;
219
220
221         /* make sure we know the assosociated tranaction ... */
222         if (t_check( p_msg  , &branch , &local_cancel)==-1)
223                 return 1;
224         /* ... if there is no such, tell the core router to forward statelessly */
225         if ( T<=0 ) return 1;
226
227         DBG("DEBUG: t_on_reply: org. status uas=%d, uac[%d]=%d loca_cancel=%d)\n",
228                 T->uas.status, branch, T->uac[branch].status, local_cancel);
229
230         /* special cases (local cancel reply) -bogdan */
231         if (local_cancel==1)
232         {
233                 reset_timer( hash_table, &(T->uac[branch].request.retr_timer));
234                 if ( p_msg->REPLY_STATUS>=200 )
235                         reset_timer(hash_table,&(T->uac[branch].request.fr_timer));
236                 goto error;
237         }
238
239         /* do we have via2 ? - maybe we'll need it for forwarding -bogdan*/
240         if ((p_msg->via2==0) || (p_msg->via2->error!=VIA_PARSE_OK)){
241                 /* no second via => error */
242                 LOG(L_ERR, "ERROR: t_on_reply: no 2nd via found in reply\n");
243                 goto error;
244         }
245
246         msg_status=p_msg->REPLY_STATUS;
247         msg_class=REPLY_CLASS(p_msg);
248         is_invite= T->uas.request->REQ_METHOD==METHOD_INVITE;
249
250         /*  generate the retrans buffer, make a simplified
251         assumption everything but 100 will be fwd-ed;
252         sometimes it will result in useless CPU cycles
253         but mostly the assumption holds and allows the
254         work to be done out of criticial lock region */
255         if (msg_status==100 && T->uac[branch].status)
256                 buf=0;
257         else {
258                 /* buf maybe allo'ed*/
259                 buf = build_res_buf_from_sip_res ( p_msg, &res_len);
260                 if (!buf) {
261                         LOG(L_ERR, "ERROR: t_on_reply_received: "
262                         "no mem for outbound reply buffer\n");
263                         goto error;
264                 }
265         }
266
267         /* *** stop timers *** */
268         /* stop retransmission */
269         reset_timer( hash_table, &(T->uac[branch].request.retr_timer));
270         /* stop final response timer only if I got a final response */
271         if ( msg_class>1 )
272                 reset_timer( hash_table, &(T->uac[branch].request.fr_timer));
273
274         LOCK_REPLIES( T );
275         /* if a got the first prov. response for an INVITE ->
276            change FR_TIME_OUT to INV_FR_TIME_UT */
277         start_fr = !T->uac[branch].rpl_received && msg_class==1 && is_invite;
278
279         /* *** store and relay message as needed *** */
280         relay = t_should_relay_response( T , msg_status, branch, &save_clone );
281         DBG("DEBUG: t_on_reply: branch=%d, save=%d, relay=%d\n",
282                 branch, save_clone, relay );
283
284         if (save_clone)
285         {
286                 str_foo = &(T->uac[branch].tag);
287                 str_foo->s = shm_resize(str_foo->s, (str_foo?0:TAG_OVERBUFFER_LEN) +
288                         get_to(p_msg)->tag_value.len);
289                 if (!str_foo->s)
290                 {
291                         LOG( L_ERR , "ERROR: t_on_reply: connot alocate memory!\n");
292                         goto error1;
293                 }
294                 /* when forking, replies greater then 300 are saved */
295                 if ((T->nr_of_outgoings>1 || T->uac[T->nr_of_outgoings].uri.s)
296                         && msg_status>=300 )
297                 {
298                         DBG("DEBUG: t_on_reply: saving reply! \n");
299                         str_foo = &(T->uac[branch].rpl_buffer);
300                         str_foo->s = shm_resize(str_foo->s, res_len+
301                                 (str_foo->s?0:REPLY_OVERBUFFER_LEN) );
302                         if (!str_foo->s)
303                         {
304                                 LOG( L_ERR , "ERROR: t_on_reply: connot alocate memory!\n");
305                                 goto error1;
306                         }
307                         memcpy(str_foo->s,buf,res_len);
308                         str_foo->len = res_len;
309                 }
310                 /*copy the TO tag from reply*/
311                 T->uac[branch].tag.len = get_to(p_msg)->tag_value.len;
312                 memcpy( T->uac[branch].tag.s, get_to(p_msg)->tag_value.s,
313                         T->uac[branch].tag.len );
314                 T->uac[branch].rpl_received = 1;
315                 T->uac[branch].status = msg_status;
316         }
317
318         rb = & T->uas.response;
319         if (relay >= 0  && (relay=check_for_no_response(T,msg_status,relay))>=0 ) {
320                 if (relay!=branch)
321                 {
322                         str_foo = &(T->uac[relay].rpl_buffer);
323                         if (buf) pkg_free(buf);
324                         buf = (char*)pkg_malloc(str_foo->len);
325                         if (!buf)
326                         {
327                                 UNLOCK_REPLIES( T );
328                                 start_fr = 1;
329                                 LOG(L_ERR, "ERROR: t_on_reply: cannot alloc pkg mem\n");
330                                 goto error1;
331                         }
332                         memcpy( buf , str_foo->s , str_foo->len );
333                         res_len = str_foo->len;
334                 }
335                 /* if there is no reply yet, initialize the structure */
336                 if ( ! rb->buffer ) {
337                         /*init retrans buffer*/
338                         if (update_sock_struct_from_via( &(rb->to),p_msg->via2 )==-1) {
339                                 UNLOCK_REPLIES( T );
340                                 start_fr = 1;
341                                 LOG(L_ERR, "ERROR: t_on_reply: cannot lookup reply dst: %s\n",
342                                         p_msg->via2->host.s );
343                                 goto error1;
344                         }
345                         rb->to.sin_family = AF_INET;
346                         rb->activ_type = p_msg->REPLY_STATUS;
347                         /* allocate something more for the first message;
348                            subsequent messages will be longer and buffer
349                            reusing will save us a malloc lock */
350                         alloc_len = res_len + REPLY_OVERBUFFER_LEN ;
351                 }else{
352                         alloc_len = res_len;
353                 }
354                 /* puts the reply's buffer to uas.response */
355                 if (! (rb->buffer = (char*)shm_resize( rb->buffer, alloc_len ))) {
356                         UNLOCK_REPLIES( T );
357                         start_fr = 1;
358                         LOG(L_ERR, "ERROR: t_on_reply: cannot alloc shmem\n");
359                         goto error1;
360                 }
361                 rb->buffer_len = res_len;
362                 memcpy( rb->buffer, buf, res_len );
363                 /* update the status ... */
364                 T->uas.status = p_msg->REPLY_STATUS;
365                 T->uas.tag=&(T->uac[relay].tag);
366                 if (T->uas.status >=200 && T->relaied_reply_branch==-1 )
367                                 T->relaied_reply_branch = relay;
368         }; /* if relay ... */
369
370         UNLOCK_REPLIES( T );
371
372         if (relay >= 0) {
373                 SEND_PR_BUFFER( rb, buf, res_len );
374                 t_update_timers_after_sending_reply( rb );
375                 callback_event( TMCB_REPLY, p_msg );
376         }
377
378         /* *** ACK handling *** */
379         if ( is_invite ) {
380                 if ( T->uac[branch].request.ack_len )
381                 {   /*retransmit*/
382                         /* I don't need any additional syncing here -- after ack
383                            is introduced it's never changed */
384                         DBG("DEBUG: localy cached ACK retranmitted\n");
385                         SEND_ACK_BUFFER( &(T->uac[branch].request) );
386                 } else if (msg_class>2 ) {
387                         /*on a non-200 reply to INVITE*/
388                         DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE:"
389                                 "send ACK\n");
390                         ack = build_ack( p_msg, T, branch , &ack_len);
391                         if (ack) {
392                                 SEND_PR_BUFFER( &(T->uac[branch].request), ack, ack_len );
393                                 /* append to transaction structure */
394                                 attach_ack( T, branch, ack , ack_len );
395                         } else {
396                                 /* restart FR */
397                                 start_fr=1;
398                                 DBG("ERROR: t_on_reply: build_ack failed\n");
399                         }
400                 }
401         } /* is_invite */
402
403         /* restart retransmission if a provisional response came for
404            a non_INVITE -> retrasmit at RT_T2*/
405         if ( msg_class==1 && !is_invite )
406         {
407                 rb->retr_list = RT_T2;
408                 set_timer( hash_table, &(rb->retr_timer), RT_T2 );
409         }
410 error1:
411         if (start_fr)
412                 set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST );
413         if (buf) pkg_free( buf );
414 error:
415         T_UNREF( T );
416         /* don't try to relay statelessly on error; on troubles, simply do nothing;
417            that will make the other party to retransmit; hopefuly, we'll then 
418            be better off */
419         return 0;
420 }
421