00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include <stdio.h>
00050 #include <string.h>
00051 #include <stdlib.h>
00052
00053 #include "../../sr_module.h"
00054 #include "../../dprint.h"
00055 #include "../../error.h"
00056 #include "../../ut.h"
00057 #include "../../script_cb.h"
00058 #include "../../mem/mem.h"
00059 #include "../../pvar.h"
00060
00061 #include "../tm/tm_load.h"
00062
00063 #include "sl_funcs.h"
00064 #include "sl_api.h"
00065 #include "sl_cb.h"
00066
00067 MODULE_VERSION
00068
00069
00070 static int w_sl_send_reply(struct sip_msg* msg, char* str1, char* str2);
00071 static int w_send_reply(struct sip_msg* msg, char* str1, char* str2);
00072 static int w_sl_reply_error(struct sip_msg* msg, char* str1, char* str2);
00073 static int fixup_sl_send_reply(void** param, int param_no);
00074 static int mod_init(void);
00075 static void mod_destroy(void);
00076
00077 int sl_enable_stats = 1;
00078 int sl_bind_tm = 1;
00079
00080
00081 stat_var *tx_1xx_rpls;
00082 stat_var *tx_2xx_rpls;
00083 stat_var *tx_3xx_rpls;
00084 stat_var *tx_4xx_rpls;
00085 stat_var *tx_5xx_rpls;
00086 stat_var *tx_6xx_rpls;
00087 stat_var *sent_rpls;
00088 stat_var *sent_err_rpls;
00089 stat_var *rcv_acks;
00090
00091 static struct tm_binds tmb;
00092
00093 static cmd_export_t cmds[]={
00094 {"sl_send_reply", (cmd_function)w_sl_send_reply,
00095 2, fixup_sl_send_reply, 0,
00096 REQUEST_ROUTE | ERROR_ROUTE },
00097 {"send_reply", (cmd_function)w_send_reply,
00098 2, fixup_sl_send_reply, 0,
00099 REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE|ERROR_ROUTE },
00100 {"sl_reply_error", (cmd_function)w_sl_reply_error,
00101 0, 0, 0, REQUEST_ROUTE},
00102 {"register_slcb", (cmd_function)register_slcb,
00103 0, 0, 0,
00104 0},
00105 {"load_sl", (cmd_function)load_sl,
00106 0, 0, 0,
00107 0},
00108 {0,0,0,0,0,0}
00109 };
00110
00111
00112 static param_export_t mod_params[]={
00113 { "enable_stats", INT_PARAM, &sl_enable_stats },
00114 { "bind_tm", INT_PARAM, &sl_bind_tm },
00115 { 0,0,0 }
00116 };
00117
00118
00119 stat_export_t mod_stats[] = {
00120 {"1xx_replies" , 0, &tx_1xx_rpls },
00121 {"2xx_replies" , 0, &tx_2xx_rpls },
00122 {"3xx_replies" , 0, &tx_3xx_rpls },
00123 {"4xx_replies" , 0, &tx_4xx_rpls },
00124 {"5xx_replies" , 0, &tx_5xx_rpls },
00125 {"6xx_replies" , 0, &tx_6xx_rpls },
00126 {"sent_replies" , 0, &sent_rpls },
00127 {"sent_err_replies" , 0, &sent_err_rpls },
00128 {"received_ACKs" , 0, &rcv_acks },
00129 {0,0,0}
00130 };
00131
00132
00133 struct module_exports exports= {
00134 "sl",
00135 DEFAULT_DLFLAGS,
00136 cmds,
00137 mod_params,
00138 mod_stats,
00139 0,
00140 0,
00141 0,
00142 mod_init,
00143 0,
00144 mod_destroy,
00145 0
00146 };
00147
00148
00149 static int mod_init(void)
00150 {
00151 load_tm_f load_tm;
00152
00153
00154 if (sl_enable_stats==0)
00155 exports.stats = 0;
00156
00157
00158 if (register_script_cb(sl_filter_ACK, PRE_SCRIPT_CB|REQ_TYPE_CB, 0 )!=0) {
00159 LM_ERR("register_script_cb failed\n");
00160 return -1;
00161 }
00162
00163
00164 if (sl_startup()!=0) {
00165 LM_ERR("sl_startup failed\n");
00166 return -1;
00167 }
00168
00169 if(sl_bind_tm!=0)
00170 {
00171 if ( (load_tm=(load_tm_f)find_export("load_tm", 0, 0)))
00172 {
00173 load_tm( &tmb );
00174 } else {
00175 LM_INFO("could not bind tm module - only stateless mode available\n");
00176 sl_bind_tm=0;
00177 }
00178 }
00179
00180 return 0;
00181 }
00182
00183
00184 static void mod_destroy(void)
00185 {
00186 sl_shutdown();
00187 destroy_slcb_lists();
00188
00189 }
00190
00191
00192
00193
00194 static int fixup_sl_send_reply(void** param, int param_no)
00195 {
00196 pv_elem_t *model=NULL;
00197 str s;
00198
00199
00200 s.s = (char*)*param;
00201 s.len = strlen(s.s);
00202
00203 model=NULL;
00204 if (param_no==1 || param_no==2)
00205 {
00206 if(s.len==0)
00207 {
00208 LM_ERR("no param %d!\n", param_no);
00209 return E_UNSPEC;
00210 }
00211
00212 if(pv_parse_format(&s ,&model) || model==NULL)
00213 {
00214 LM_ERR("wrong format [%s] for param no %d!\n", s.s, param_no);
00215 return E_UNSPEC;
00216 }
00217 if(model->spec.getf==NULL)
00218 {
00219 if(param_no==1)
00220 {
00221 if(str2int(&s,
00222 (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n)!=0
00223 || model->spec.pvp.pvn.u.isname.name.n<100
00224 || model->spec.pvp.pvn.u.isname.name.n>699)
00225 {
00226 LM_ERR("wrong value [%s] for param no %d!\n",
00227 s.s, param_no);
00228 LM_ERR("allowed values: 1xx - 6xx only!\n");
00229 return E_UNSPEC;
00230 }
00231 }
00232 }
00233 *param = (void*)model;
00234 }
00235
00236 return 0;
00237 }
00238
00239
00240
00241
00242
00243 static int w_sl_reply_error( struct sip_msg* msg, char* str1, char* str2)
00244 {
00245 return sl_reply_error( msg );
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 static int w_sl_send_reply(struct sip_msg* msg, char* str1, char* str2)
00255 {
00256 str code_s;
00257 unsigned int code_i;
00258
00259 if(((pv_elem_p)str1)->spec.getf!=NULL)
00260 {
00261 if(pv_printf_s(msg, (pv_elem_p)str1, &code_s)!=0)
00262 return -1;
00263 if(str2int(&code_s, &code_i)!=0 || code_i<100 || code_i>699)
00264 return -1;
00265 } else {
00266 code_i = ((pv_elem_p)str1)->spec.pvp.pvn.u.isname.name.n;
00267 }
00268
00269 if(((pv_elem_p)str2)->spec.getf!=NULL)
00270 {
00271 if(pv_printf_s(msg, (pv_elem_p)str2, &code_s)!=0 || code_s.len <=0)
00272 return -1;
00273 } else {
00274 code_s = ((pv_elem_p)str2)->text;
00275 }
00276
00277 return sl_send_reply(msg, code_i, &code_s);
00278 }
00279
00280 int send_reply(struct sip_msg *msg, int code, str *text)
00281 {
00282 struct cell * t;
00283 if(sl_bind_tm!=0)
00284 {
00285 t = tmb.t_gett();
00286 if(t!= NULL && t!=T_UNDEFINED)
00287 {
00288 if(tmb.t_reply(msg, code, text)< 0)
00289 {
00290 LM_ERR("failed to reply stateful (tm)\n");
00291 return -1;
00292 }
00293 LM_DBG("reply in stateful mode (tm)\n");
00294 return 1;
00295 }
00296 }
00297
00298 LM_DBG("reply in stateless mode (sl)\n");
00299 return sl_send_reply(msg, code, text);
00300 }
00301
00302 static int w_send_reply(struct sip_msg* msg, char* str1, char* str2)
00303 {
00304 str code_s;
00305 unsigned int code_i;
00306
00307 if(((pv_elem_p)str1)->spec.getf!=NULL)
00308 {
00309 if(pv_printf_s(msg, (pv_elem_p)str1, &code_s)!=0)
00310 return -1;
00311 if(str2int(&code_s, &code_i)!=0 || code_i<100 || code_i>699)
00312 return -1;
00313 } else {
00314 code_i = ((pv_elem_p)str1)->spec.pvp.pvn.u.isname.name.n;
00315 }
00316
00317 if(((pv_elem_p)str2)->spec.getf!=NULL)
00318 {
00319 if(pv_printf_s(msg, (pv_elem_p)str2, &code_s)!=0 || code_s.len <=0)
00320 return -1;
00321 } else {
00322 code_s = ((pv_elem_p)str2)->text;
00323 }
00324 return send_reply(msg, code_i, &code_s);
00325 }
00326
00327
00328 int get_reply_totag(struct sip_msg *msg, str *totag)
00329 {
00330 struct cell * t;
00331 if(msg==NULL || totag==NULL)
00332 return -1;
00333 if(sl_bind_tm!=0)
00334 {
00335 t = tmb.t_gett();
00336 if(t!= NULL && t!=T_UNDEFINED)
00337 {
00338 if(tmb.t_get_reply_totag(msg, totag)< 0)
00339 {
00340 LM_ERR("failed to get totag (tm)\n");
00341 return -1;
00342 }
00343 LM_DBG("totag stateful mode (tm)\n");
00344 return 1;
00345 }
00346 }
00347
00348 LM_DBG("totag stateless mode (sl)\n");
00349 return sl_get_reply_totag(msg, totag);
00350 }
00351
00352
00353
00354
00355
00356
00357 int load_sl( struct sl_binds *slb)
00358 {
00359 if(slb==NULL)
00360 return -1;
00361
00362 slb->reply = sl_send_reply;
00363 slb->reply_dlg = sl_send_reply_dlg;
00364 slb->sl_get_reply_totag = sl_get_reply_totag;
00365 slb->send_reply = send_reply;
00366 slb->get_reply_totag = get_reply_totag;
00367
00368
00369 return 1;
00370 }