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
00057 #include <stdio.h>
00058 #include <string.h>
00059 #include <stdlib.h>
00060
00061 #include "../../sr_module.h"
00062 #include "../../dprint.h"
00063 #include "../../error.h"
00064 #include "../../ut.h"
00065 #include "../../script_cb.h"
00066 #include "../../mem/mem.h"
00067
00068 #include "../../modules/tm/tm_load.h"
00069
00070 #include "sl_stats.h"
00071 #include "sl_funcs.h"
00072 #include "sl.h"
00073
00074 MODULE_VERSION
00075
00076 static int default_code = 500;
00077 static str default_reason = STR_STATIC_INIT("Internal Server Error");
00078
00079 int _sl_filtered_ack_route = -1;
00080
00081 static int sl_bind_tm = 1;
00082 static struct tm_binds tmb;
00083
00084 static int w_sl_send_reply(struct sip_msg* msg, char* str, char* str2);
00085 static int w_send_reply(struct sip_msg* msg, char* str1, char* str2);
00086 static int w_sl_reply_error(struct sip_msg* msg, char* str, char* str2);
00087 static int bind_sl(sl_api_t* api);
00088 static int mod_init(void);
00089 static int child_init(int rank);
00090 static void mod_destroy();
00091 static int fixup_sl_reply(void** param, int param_no);
00092
00093 static cmd_export_t cmds[]={
00094 {"sl_send_reply", w_sl_send_reply, 2, fixup_sl_reply,
00095 REQUEST_ROUTE},
00096 {"sl_reply", w_sl_send_reply, 2, fixup_sl_reply,
00097 REQUEST_ROUTE},
00098 {"send_reply", w_send_reply, 2, fixup_sl_reply,
00099 REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
00100 {"sl_reply_error", w_sl_reply_error, 0, 0,
00101 REQUEST_ROUTE},
00102 {"bind_sl", (cmd_function)bind_sl, 0, 0, 0},
00103 {0,0,0,0,0}
00104 };
00105
00106
00107
00108
00109
00110 static param_export_t params[] = {
00111 {"default_code", PARAM_INT, &default_code},
00112 {"default_reason", PARAM_STR, &default_reason},
00113 {"bind_tm", PARAM_INT, &sl_bind_tm},
00114
00115 {0, 0, 0}
00116 };
00117
00118
00119 #ifdef STATIC_SL
00120 struct module_exports sl_exports = {
00121 #else
00122 struct module_exports exports= {
00123 #endif
00124 "sl",
00125 cmds,
00126 sl_rpc,
00127 params,
00128 mod_init,
00129 (response_function) 0,
00130 mod_destroy,
00131 0,
00132 child_init
00133 };
00134
00135
00136 static int mod_init(void)
00137 {
00138 if (init_sl_stats() < 0) {
00139 ERR("init_sl_stats failed\n");
00140 return -1;
00141 }
00142 if (sl_register_kstats()<0) {
00143 ERR("init k stats failed\n");
00144 return -1;
00145 }
00146
00147
00148 if (register_script_cb( sl_filter_ACK, PRE_SCRIPT_CB|REQUEST_CB, 0 )<0) {
00149 ERR("Failed to install SCRIPT callback\n");
00150 return -1;
00151 }
00152 if(sl_startup()<0)
00153 {
00154 ERR("Failed to do startup tasks\n");
00155 return -1;
00156 }
00157
00158 if(sl_bind_tm!=0)
00159 {
00160 if(load_tm_api(&tmb)==-1)
00161 {
00162 LM_INFO("could not bind tm module - only stateless mode"
00163 " available\n");
00164 sl_bind_tm=0;
00165 }
00166 }
00167
00168 _sl_filtered_ack_route=route_lookup(&event_rt, "sl:filtered-ack");
00169 if (_sl_filtered_ack_route>=0 && event_rt.rlist[_sl_filtered_ack_route]==0)
00170 _sl_filtered_ack_route=-1;
00171
00172 return 0;
00173 }
00174
00175 static int child_init(int rank)
00176 {
00177 if (rank == PROC_INIT) {
00178 if (init_sl_stats_child() < 0) {
00179 ERR("init_sl_stats_child failed\n");
00180 return -1;
00181 }
00182 }
00183 return 0;
00184 }
00185
00186
00187 static void mod_destroy()
00188 {
00189 sl_stats_destroy();
00190 sl_shutdown();
00191 }
00192
00193
00201 static int w_sl_send_reply(struct sip_msg* msg, char* p1, char* p2)
00202 {
00203 int code, ret;
00204 str reason;
00205 char* r;
00206
00207 if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) {
00208 code = default_code;
00209 }
00210
00211 if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) {
00212 reason = default_reason;;
00213 }
00214
00215 if(reason.s[reason.len-1]=='\0') {
00216 r = reason.s;
00217 } else {
00218 r = as_asciiz(&reason);
00219 if (r == NULL) r = default_reason.s;
00220 }
00221 ret = sl_send_reply(msg, code, r);
00222 if (r!=reason.s) pkg_free(r);
00223 return ret;
00224 }
00225
00226
00230 static int w_sl_reply_error( struct sip_msg* msg, char* str, char* str2)
00231 {
00232 return sl_reply_error( msg );
00233 }
00234
00246 int send_reply(struct sip_msg *msg, int code, str *reason)
00247 {
00248 char *r = NULL;
00249 struct cell *t;
00250 int ret = 1;
00251
00252 if(reason->s[reason->len-1]=='\0') {
00253 r = reason->s;
00254 } else {
00255 r = as_asciiz(reason);
00256 if (r == NULL)
00257 {
00258 LM_ERR("no pkg for reason phrase\n");
00259 return -1;
00260 }
00261 }
00262
00263 if(sl_bind_tm!=0)
00264 {
00265 t = tmb.t_gett();
00266 if(t!= NULL && t!=T_UNDEFINED)
00267 {
00268 if(tmb.t_reply(msg, code, r)< 0)
00269 {
00270 LM_ERR("failed to reply stateful (tm)\n");
00271 goto error;
00272 }
00273 LM_DBG("reply in stateful mode (tm)\n");
00274 goto done;
00275 }
00276 }
00277
00278 LM_DBG("reply in stateless mode (sl)\n");
00279 ret = sl_send_reply(msg, code, r);
00280
00281 done:
00282 if(r!=reason->s) pkg_free(r);
00283 return ret;
00284
00285 error:
00286 if(r!=reason->s) pkg_free(r);
00287 return -1;
00288 }
00289
00293 static int w_send_reply(struct sip_msg* msg, char* p1, char* p2)
00294 {
00295 int code;
00296 str reason;
00297
00298 if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) {
00299 code = default_code;
00300 }
00301
00302 if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) {
00303 reason = default_reason;
00304 }
00305
00306 return send_reply(msg, code, &reason);
00307 }
00308
00312 int get_reply_totag(struct sip_msg *msg, str *totag)
00313 {
00314 struct cell * t;
00315 if(msg==NULL || totag==NULL)
00316 return -1;
00317 if(sl_bind_tm!=0)
00318 {
00319 t = tmb.t_gett();
00320 if(t!= NULL && t!=T_UNDEFINED)
00321 {
00322 if(tmb.t_get_reply_totag(msg, totag)< 0)
00323 {
00324 LM_ERR("failed to get totag (tm)\n");
00325 return -1;
00326 }
00327 LM_DBG("totag stateful mode (tm)\n");
00328 return 1;
00329 }
00330 }
00331
00332 LM_DBG("totag stateless mode (sl)\n");
00333 return sl_get_reply_totag(msg, totag);
00334 }
00335
00336
00340 static int fixup_sl_reply(void** param, int param_no)
00341 {
00342 if (param_no == 1) {
00343 return fixup_var_int_12(param, 1);
00344 } else if (param_no == 2) {
00345 return fixup_var_pve_str_12(param, 2);
00346 }
00347 return 0;
00348 }
00349
00350
00354 static int bind_sl(sl_api_t* api)
00355 {
00356 if (!api) {
00357 ERR("Invalid parameter value\n");
00358 return -1;
00359 }
00360 api->zreply = sl_send_reply;
00361 api->sreply = sl_send_reply_str;
00362 api->dreply = sl_send_reply_dlg;
00363 api->freply = send_reply;
00364 api->get_reply_totag = get_reply_totag;
00365 api->register_cb = sl_register_callback;
00366
00367 return 0;
00368 }