xr_server.c
Go to the documentation of this file.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 #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
00072 if (mi_rpl)
00073 free_mi_tree( mi_rpl );
00074 return;
00075 }
00076
00077
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
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
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 }