xr_server.c

Go to the documentation of this file.
00001 /*
00002  * $Id: xr_server.c 4585 2008-08-06 08:20:30Z klaus_darilion $
00003  *
00004  * Copyright (C) 2006 Voice Sistem SRL
00005  *
00006  * This file is part of Kamailio.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00021  *
00022  * History:
00023  * ---------
00024  *  2006-11-30  first version (lavinia)
00025  *  2007-02-02  support for asyncronous reply added (bogdan)
00026  *  2007-10-05  support for libxmlrpc-c3 version 1.x.x added (dragos)
00027  */
00028 
00029 
00030 #include "../../str.h"
00031 #include "../../dprint.h"
00032 #include "../../sr_module.h"
00033 #include "../../mi/mi.h"
00034 #include "../../mem/mem.h"
00035 #include "../../mem/shm_mem.h"
00036 #include "../../locking.h"
00037 #include "../../ut.h"
00038 #include "xr_writer.h"
00039 #include "xr_parser.h"
00040 #include "mi_xmlrpc.h"
00041 #include "xr_server.h"
00042 
00043 #ifdef XMLRPC_OLD_VERSION
00044 #include <xmlrpc_abyss.h>
00045 #endif
00046 
00047 
00048 gen_lock_t *xr_lock;
00049 
00050 #define XMLRPC_ASYNC_FAILED   ((void*)-2)
00051 #define XMLRPC_ASYNC_EXPIRED  ((void*)-3)
00052 
00053 
00054 
00055 
00056 static inline void free_async_handler( struct mi_handler *hdl )
00057 {
00058    if (hdl)
00059       shm_free(hdl);
00060 }
00061 
00062 
00063 
00064 static void xmlrpc_close_async( struct mi_root *mi_rpl, struct mi_handler *hdl,
00065                                                    int done)
00066 {
00067    struct mi_root *shm_rpl;
00068    int x;
00069 
00070    if (!done) {
00071       /* we do not pass provisional stuff (yet) */
00072       if (mi_rpl)
00073          free_mi_tree( mi_rpl );
00074       return;
00075    }
00076 
00077    /* pass the tree via handler back to originating process */
00078    if ( mi_rpl==NULL || (shm_rpl=clone_mi_tree( mi_rpl, 1))==NULL )
00079       shm_rpl = XMLRPC_ASYNC_FAILED;
00080    if (mi_rpl)
00081       free_mi_tree(mi_rpl);
00082 
00083    lock_get(xr_lock);
00084    if (hdl->param==NULL) {
00085       hdl->param = shm_rpl;
00086       x = 0;
00087    } else {
00088       x = 1;
00089    }
00090    lock_release(xr_lock);
00091 
00092    if (x) {
00093       if (shm_rpl!=XMLRPC_ASYNC_FAILED)
00094          free_shm_mi_tree(shm_rpl);
00095       free_async_handler(hdl);
00096    }
00097 }
00098 
00099 
00100 #define MAX_XMLRPC_WAIT 2*60*4
00101 static inline struct mi_root* wait_async_reply(struct mi_handler *hdl)
00102 {
00103    struct mi_root *mi_rpl;
00104    int i;
00105    int x;
00106 
00107    for( i=0 ; i<MAX_XMLRPC_WAIT ; i++ ) {
00108       if (hdl->param)
00109          break;
00110       sleep_us(1000*500);
00111    }
00112 
00113    if (i==MAX_XMLRPC_WAIT) {
00114       /* no more waiting ....*/
00115       lock_get(xr_lock);
00116       if (hdl->param==NULL) {
00117          hdl->param = XMLRPC_ASYNC_EXPIRED;
00118          x = 0;
00119       } else {
00120          x = 1;
00121       }
00122       lock_release(xr_lock);
00123       if (x==0) {
00124          LM_INFO("exiting before receiving reply\n");
00125          return NULL;
00126       }
00127    }
00128 
00129    mi_rpl = (struct mi_root *)hdl->param;
00130    if (mi_rpl==XMLRPC_ASYNC_FAILED)
00131       mi_rpl = NULL;
00132 
00133    free_async_handler(hdl);
00134    return mi_rpl;
00135 }
00136 
00137 
00138 
00139 static inline struct mi_handler* build_async_handler(void)
00140 {
00141    struct mi_handler *hdl;
00142 
00143    hdl = (struct mi_handler*)shm_malloc( sizeof(struct mi_handler) );
00144    if (hdl==0) {
00145       LM_ERR("no more shm mem\n");
00146       return 0;
00147    }
00148 
00149    hdl->handler_f = xmlrpc_close_async;
00150    hdl->param = 0;
00151 
00152    return hdl;
00153 }
00154 
00155 
00156 #ifdef XMLRPC_OLD_VERSION
00157 xmlrpc_value*  default_method (xmlrpc_env*   env, 
00158                         char*          host,
00159                         char*          methodName,
00160                         xmlrpc_value*  paramArray,
00161                         void*          serverInfo)
00162 #else
00163 xmlrpc_value*  default_method (xmlrpc_env*   env, 
00164                         const char*    host,
00165                         const char*    methodName,
00166                         xmlrpc_value*  paramArray,
00167                         void*          serverInfo)
00168 #endif
00169 {
00170    xmlrpc_value* ret = NULL;
00171    struct mi_root* mi_cmd = NULL;
00172    struct mi_root* mi_rpl = NULL;
00173    struct mi_handler *hdl = NULL;
00174    struct mi_cmd* f;
00175    char* response = 0;
00176    int is_shm = 0;
00177 
00178    LM_DBG("starting up.....\n");
00179 
00180    f = lookup_mi_cmd((char*)methodName, strlen(methodName));
00181    
00182    if ( f == 0 ) {
00183       LM_ERR("command %s is not available!\n", methodName);
00184       xmlrpc_env_set_fault_formatted(env, XMLRPC_NO_SUCH_METHOD_ERROR, 
00185          "Requested command (%s) is not available!", methodName);
00186       goto error;
00187    }
00188 
00189    LM_DBG("done looking the mi command.\n");
00190 
00191    /* if asyncron cmd, build the async handler */
00192    if (f->flags&MI_ASYNC_RPL_FLAG) {
00193       hdl = build_async_handler( );
00194       if (hdl==0) {
00195          LM_ERR("failed to build async handler\n");
00196          if ( !env->fault_occurred )
00197             xmlrpc_env_set_fault(env, XMLRPC_INTERNAL_ERROR,
00198                "Internal server error while processing request");
00199          goto error;
00200       }
00201    } else {
00202       hdl = NULL;
00203    }
00204 
00205    if (f->flags&MI_NO_INPUT_FLAG) {
00206       mi_cmd = 0;
00207    } else {
00208       mi_cmd = xr_parse_tree(env, paramArray);
00209       if ( mi_cmd == NULL ){
00210          LM_ERR("failed to parse MI tree\n");
00211          if ( !env->fault_occurred )
00212             xmlrpc_env_set_fault(env, XMLRPC_INTERNAL_ERROR,
00213                "The xmlrpc request could not be parsed into a MI tree!");
00214          goto error;
00215       }
00216       mi_cmd->async_hdl = hdl;
00217    }
00218 
00219    LM_DBG("done parsing the mi tree.\n");
00220 
00221    if ( ( mi_rpl = run_mi_cmd(f, mi_cmd) ) == 0 ){
00222       LM_ERR("command (%s) processing failed.\n", methodName);
00223       xmlrpc_env_set_fault_formatted(env, XMLRPC_INTERNAL_ERROR, 
00224          "Command (%s) processing failed.\n", methodName);
00225       goto error;
00226    } else if (mi_rpl==MI_ROOT_ASYNC_RPL) {
00227       mi_rpl = wait_async_reply(hdl);
00228       hdl = 0;
00229       if (mi_rpl==0) {
00230          xmlrpc_env_set_fault_formatted(env, XMLRPC_INTERNAL_ERROR, 
00231             "Command (%s) processing failed (async).\n", methodName);
00232          goto error;
00233       }
00234       is_shm = 1;
00235    }
00236 
00237    LM_DBG("done running the mi command.\n");
00238 
00239    if ( rpl_opt == 1 ) {
00240       if ( xr_build_response_array( env, mi_rpl ) != 0 ){
00241          if ( !env->fault_occurred ) {
00242             LM_ERR("failed parsing the xmlrpc response from the mi tree\n");
00243             xmlrpc_env_set_fault(env, XMLRPC_INTERNAL_ERROR, 
00244                "Failed to parse the xmlrpc response from the mi tree.");
00245             }
00246          goto error;
00247       }
00248       LM_DBG("done building response array.\n");
00249 
00250       ret = xr_response;
00251    } else {
00252       if ( (response = xr_build_response( env, mi_rpl )) == 0 ){
00253          if ( !env->fault_occurred ) {
00254             LM_ERR("failed parsing the xmlrpc response from the mi tree\n");
00255             xmlrpc_env_set_fault_formatted(env, XMLRPC_INTERNAL_ERROR,
00256                "Failed to parse the xmlrpc response from the mi tree.");
00257          }
00258          goto error;
00259       }
00260       LM_DBG("done building response.\n");
00261 
00262       ret = xmlrpc_build_value(env, "s", response);
00263    }
00264 
00265 error:
00266    free_async_handler(hdl);
00267    if ( mi_cmd ) free_mi_tree( mi_cmd );
00268    if ( mi_rpl ) { is_shm?free_shm_mi_tree(mi_rpl):free_mi_tree(mi_rpl);}
00269    return ret;
00270 }
00271 
00272 
00273 int set_default_method ( xmlrpc_env * env ,  xmlrpc_registry * registry)
00274 {
00275    xmlrpc_registry_set_default_method(env, registry, &default_method, NULL);
00276 
00277    if ( env->fault_occurred ) {
00278       LM_ERR("failed to add default method: %s\n", env->fault_string);
00279       return -1;
00280    }
00281 
00282    return 0;
00283 }
00284 
00285 int init_async_lock(void)
00286 {
00287    xr_lock = lock_alloc();
00288    if (xr_lock==NULL) {
00289       LM_ERR("failed to create lock\n");
00290       return -1;
00291    }
00292    if (lock_init(xr_lock)==NULL) {
00293       LM_ERR("failed to init lock\n");
00294       return -1;
00295    }
00296 
00297    return 0;
00298 }
00299 
00300 void destroy_async_lock(void)
00301 {
00302    if (xr_lock) {
00303       lock_destroy(xr_lock);
00304       lock_dealloc(xr_lock);
00305    }
00306 }

Generated on Fri May 25 00:00:35 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6