memory access syncing protection added
[sip-router] / modules / tm / t_funcs.h
1 /*
2  * $Id$
3  */
4
5
6 #ifndef _T_FUNCS_H
7 #define _T_FUNCS_H
8
9 #include <errno.h>
10 #include <netinet/in.h>
11 #include <netdb.h>
12 #include "../../msg_parser.h"
13 #include "../../globals.h"
14 #include "../../udp_server.h"
15 #include "../../msg_translator.h"
16 #include "../../forward.h"
17 #include "../../mem/mem.h"
18
19 struct s_table;
20 struct timer;
21 struct entry;
22 struct cell;
23
24 extern struct cell         *T;
25 extern unsigned int     global_msg_id;
26 extern struct s_table*  hash_table;
27
28
29 #include "sh_malloc.h"
30
31 #include "timer.h"
32 #include "lock.h"
33 #include "sip_msg.h"
34
35
36 #define LOCK_REPLIES(_t) lock((_t)->reply_mutex )
37 #define UNLOCK_REPLIES(_t) unlock((_t)->reply_mutex )
38 #define LOCK_ACK(_t) lock((_t)->ack_mutex )
39 #define UNLOCK_ACK(_t) unlock((_t)->ack_mutex )
40
41
42 /* convenience short-cut macros */
43 #define REQ_METHOD first_line.u.request.method_value
44 #define REPLY_STATUS first_line.u.reply.statuscode
45 #define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
46 #define SEND_BUFFER( _rb ) ({ if ((_rb)->retr_buffer) \
47         { udp_send( (_rb)->retr_buffer, \
48           (_rb)->bufflen, (struct sockaddr*)&((_rb)->to) , \
49           sizeof(struct sockaddr_in) ); \
50         } else \
51         DBG("ERROR: attempt to send an empty buffer from %s (%d)", \
52         __FUNCTION__, __LINE__ ); })
53
54
55 /* 
56   macros for reference bitmap (lock-less process non-exclusive ownership) 
57 */
58 #define T_IS_REFED(_T_cell) ((_T_cell)->ref_bitmap)
59 #define T_REFCOUNTER(_T_cell) \
60         ( { int _i=0; \
61                 process_bm_t _b=(_T_cell)->ref_bitmap; \
62                 while (_b) { \
63                         if ( (_b) & 1 ) _i++; \
64                         (_b) >>= 1; \
65                 } ;\
66                 (_i); \
67          } )
68                 
69
70 #ifdef EXTRA_DEBUG
71 #define T_IS_REFED_BYSELF(_T_cell) ((_T_cell)->ref_bitmap & process_bit)
72 #       define DBG_REF(_action, _t) DBG("DEBUG: XXXXX %s (%s:%d): T=%p , ref (bm=%x, cnt=%d)\n",\
73                         (_action), __FUNCTION__, __LINE__, (_t),(_t)->ref_bitmap, T_REFCOUNTER(_t));
74 #       define T_UNREF(_T_cell) \
75         ( { \
76                 DBG_REF("unref", (_T_cell)); \
77                 if (!T_IS_REFED_BYSELF(_T_cell)) { \
78                         DBG("ERROR: unrefering unrefered transaction %p from %s , %s : %d\n", \
79                                 (_T_cell), __FUNCTION__, __FILE__, __LINE__ ); \
80                         abort(); \
81                 } \
82                 (_T_cell)->ref_bitmap &= ~process_bit; \
83         } )
84
85 #       define T_REF(_T_cell) \
86         ( { \
87                 DBG_REF("ref", (_T_cell));       \
88                 if (T_IS_REFED_BYSELF(_T_cell)) { \
89                         DBG("ERROR: refering already refered transaction %p from %s , %s : %d\n", \
90                                 (_T_cell), __FUNCTION__, __FILE__, __LINE__ ); \
91                         abort(); \
92                 } \
93                 (_T_cell)->ref_bitmap |= process_bit; \
94         } )
95 #else
96 #       define T_UNREF(_T_cell) ({ (_T_cell)->ref_bitmap &= ~process_bit; })
97 #       define T_REF(_T_cell) ({ (_T_cell)->ref_bitmap |= process_bit; })
98 #endif
99
100
101         
102
103 #ifdef _OLD_XX
104 #define unref_T(_T_cell) \
105         ( {\
106                 lock( hash_table->entrys[(_T_cell)->hash_index].mutex );\
107                 (_T_cell)->ref_counter--;\
108                 DBG_REF("unref", (_T_cell)); \
109                 unlock( hash_table->entrys[(_T_cell)->hash_index].mutex );\
110         } );
111
112 /* we assume that ref_T is only called from places where
113    the associated locks are set up and we don't need to
114    lock/unlock
115 */
116 #define ref_T(_T_cell) ({ ((_T_cell)->ref_counter++); \
117                 DBG_REF("ref", (_T_cell));      })
118 #endif
119
120 enum addifnew_status { AIN_ERROR, AIN_RETR, AIN_NEW, AIN_NEWACK, AIN_OLDACK } ;
121
122
123 int   tm_startup();
124 void tm_shutdown();
125
126
127 /* function returns:
128  *       1 - a new transaction was created
129  *      -1 - error, including retransmission
130  */
131 int  t_add_transaction( struct sip_msg* p_msg  );
132
133
134
135
136 /* function returns:
137  *      -1 - transaction wasn't found
138  *       1 - transaction found
139  */
140 int t_check( struct sip_msg* , int *branch );
141
142
143
144
145 /* Forwards the inbound request to a given IP and port.  Returns:
146  *       1 - forward successfull
147  *      -1 - error during forward
148  */
149 int t_forward( struct sip_msg* p_msg , unsigned int dst_ip ,
150                                 unsigned int dst_port);
151
152
153
154
155 /* Forwards the inbound request to dest. from via.  Returns:
156  *       1 - forward successfull
157  *      -1 - error during forward
158  */
159 int t_forward_uri( struct sip_msg* p_msg  );
160
161
162
163 /*  This function is called whenever a reply for our module is received; we need to register
164   *  this function on module initialization;
165   *  Returns :   0 - core router stops
166   *                    1 - core router relay statelessly
167   */
168 int t_on_reply_received( struct sip_msg  *p_msg ) ;
169
170
171
172
173 /*  This function is called whenever a request for our module is received; we need to register
174   *  this function on module initialization;
175   *  Returns :   0 - core router stops
176   *                    1 - core router relay statelessly
177   */
178 int t_on_request_received( struct sip_msg  *p_msg , unsigned int ip, unsigned int port) ;
179
180
181
182
183 /*  This function is called whenever a request for our module is received; we need to register
184   *  this function on module initialization;
185   *  Returns :   0 - core router stops
186   *                    1 - core router relay statelessly
187   */
188 int t_on_request_received_uri( struct sip_msg  *p_msg ) ;
189
190
191
192
193 /* returns 1 if everything was OK or -1 for error
194 */
195 int t_release_transaction( struct sip_msg* );
196
197
198
199
200 /* Retransmits the last sent inbound reply.
201   * Returns  -1 -error
202   *                1 - OK
203   */
204 int t_retransmit_reply( struct sip_msg *  );
205
206
207
208
209 /* Force a new response into inbound response buffer.
210  * returns 1 if everything was OK or -1 for erro
211  */
212 int t_send_reply( struct sip_msg * , unsigned int , char *  );
213
214
215 /* releases T-context */
216 int t_unref( /* struct sip_msg* p_msg */ );
217
218 int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
219     unsigned int dest_port_param );
220 int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
221     unsigned int dest_port_param );
222
223
224
225
226 struct cell* t_lookupOriginalT(  struct s_table* hash_table , struct sip_msg* p_msg );
227 int t_reply_matching( struct sip_msg* , unsigned int*  );
228 int t_store_incoming_reply( struct cell* , unsigned int , struct sip_msg* );
229 int  t_lookup_request( struct sip_msg* p_msg , int leave_new_locked );
230 int t_all_final( struct cell * );
231 int t_build_and_send_ACK( struct cell *Trans , unsigned int brach , struct sip_msg* rpl);
232 int t_cancel_branch(unsigned int branch); //TO DO
233 int t_should_relay_response( struct cell *Trans, int new_code, int branch, int *should_store );
234 int t_update_timers_after_sending_reply( struct retrans_buff *rb );
235 int t_put_on_wait(  struct cell  *Trans  );
236 int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg );
237 static int push_reply_from_uac_to_uas( struct cell* Trans , unsigned int );
238 int add_branch_label( struct cell *Trans, struct sip_msg *p_msg , int branch );
239 int get_ip_and_port_from_uri( struct sip_msg* p_msg , unsigned int *param_ip, unsigned int *param_port);
240
241 enum addifnew_status t_addifnew( struct sip_msg* p_msg );
242
243 void retransmission_handler( void *);
244 void final_response_handler( void *);
245 void wait_handler( void *);
246 void delete_handler( void *);
247
248 inline int static send_ack( struct cell *t, int branch, 
249         struct retrans_buff *srb, int len )
250 {
251         memset( srb, 0, sizeof( struct retrans_buff ) );
252         memcpy( & srb->to, & t->ack_to, sizeof (struct sockaddr_in));
253         srb->tolen = sizeof (struct sockaddr_in);
254         srb->my_T = t;
255         srb->retr_buffer = (char *) srb + sizeof( struct retrans_buff );
256         srb->bufflen = len;
257         LOCK_ACK( t );
258         if (t->outbound_ack[branch]) {
259                 UNLOCK_ACK(t);
260                 shm_free( srb );        
261                 LOG(L_WARN, "send_ack: Warning: ACK already sent out\n");
262                 return 0;
263         }
264         t->outbound_ack[branch] = srb;
265         SEND_BUFFER( srb );
266         UNLOCK_ACK( t );
267         return 1;
268 }
269
270
271 #endif