sl.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * sl module - stateless reply
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License 
00026  * along with this program; if not, write to the Free Software 
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  */
00029 /*
00030  * History:
00031  * --------
00032  *  2003-03-11  updated to the new module exports interface (andrei)
00033  *  2003-03-16  flags export parameter added (janakj)
00034  *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free
00035  *  2005-03-01  force for stateless replies the incoming interface of
00036  *              the request (bogdan)
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; /* default disabled */
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  * Exported parameters
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,     /* RPC methods */
00127     params,     /* param exports */
00128     mod_init,   /* module initialization function */
00129     (response_function) 0,
00130     mod_destroy,
00131     0,
00132     child_init  /* per-child init function */
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         /* if SL loaded, filter ACKs on beginning */
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; /* disable */
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 }