xr_writer.c

Go to the documentation of this file.
00001 /*
00002  * $Id: xr_writer.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  */
00026 
00027 
00028 #include <string.h>
00029 #include "../../str.h"
00030 #include "../../dprint.h"
00031 #include "../../mem/mem.h"
00032 #include "xr_writer.h"
00033 #include "mi_xmlrpc.h"
00034 
00035 static char *reply_buffer = 0;
00036 static unsigned int reply_buffer_len = 0;
00037 static xmlrpc_value* reply_item;
00038 
00039 int xr_writer_init( unsigned int size )
00040 {
00041    reply_buffer_len = size;
00042 
00043    reply_buffer = pkg_malloc(size);
00044    if(!reply_buffer){
00045       LM_ERR("pkg_malloc cannot allocate any more memory!\n");
00046       return -1;
00047    }
00048    
00049    return 0;
00050 }
00051 
00052 static int xr_write_node(str * buf, struct mi_node * node)
00053 {
00054    char *end;
00055    char *p;
00056     struct mi_attr* attr;
00057 
00058    p = buf->s;
00059    end = buf->s + buf->len -1;
00060 
00061    /* name and value */
00062    if ( node->name.s != NULL ) {
00063       if ( p+node->name.len+3 > end )
00064          return -1;
00065       memcpy(p, node->name.s, node->name.len);
00066       p += node->name.len;
00067       *(p++) = ':';
00068       *(p++) = ':';
00069       *(p++) = ' ';
00070    }
00071    if ( node->value.s != NULL ) {
00072       if ( p+node->value.len > end )
00073          return -1;
00074       memcpy(p, node->value.s, node->value.len);
00075       p += node->value.len;
00076    }
00077    
00078    /* attributes */
00079    for( attr=node->attributes ; attr!=NULL ; attr=attr->next ) {
00080       if ( attr->name.s != NULL ) {
00081          if ( p+attr->name.len+2 > end )
00082             return -1;
00083          *(p++) = ' ';
00084          memcpy(p,attr->name.s,attr->name.len);
00085          p += attr->name.len;
00086          *(p++) = '=';
00087       }
00088       if (attr->value.s!=NULL) {
00089          if (p+attr->value.len>end)
00090             return -1;
00091          memcpy(p,attr->value.s,attr->value.len);
00092          p += attr->value.len;
00093       }
00094    }
00095 
00096 
00097    if ( p+1 > end )
00098       return -1;
00099    *(p++) = '\n';
00100 
00101    buf->len -= p-buf->s; 
00102    buf->s = p;
00103    return 0;
00104 }
00105 
00106 static int recur_build_response_array( xmlrpc_env * env, struct mi_node * tree, str * buf )
00107 {
00108    for ( ; tree ; tree = tree->next ) {
00109       
00110       if ( xr_write_node( buf, tree ) != 0 ) {
00111          LM_ERR("failed to get MI node data!\n");
00112          return -1;
00113       }  
00114 
00115       reply_buffer[reply_buffer_len-buf->len] = 0;
00116       reply_item = xmlrpc_build_value(env, "s", reply_buffer);
00117       xmlrpc_array_append_item(env, xr_response, reply_item);
00118       
00119       buf->s = reply_buffer; 
00120       buf->len = reply_buffer_len;
00121 
00122       if ( tree->kids ) {
00123          if ( recur_build_response_array(env, tree->kids, buf) != 0 )
00124             return -1;
00125       }
00126    }
00127    return 0;
00128 }
00129 
00130 int xr_build_response_array( xmlrpc_env * env, struct mi_root * tree )
00131 {
00132    str buf;
00133     
00134    buf.s = reply_buffer;
00135    buf.len = reply_buffer_len;
00136 
00137    /* test if mi root value is 200 OK (if not no point to continue) */
00138    if ( tree->code<200 || tree->code>=300 ){
00139       LM_DBG("command processing failure: %s\n", tree->reason.s); 
00140       if (tree->reason.s)
00141          xmlrpc_env_set_fault(env, tree->code, tree->reason.s);
00142       else
00143          xmlrpc_env_set_fault(env, tree->code, "Error");
00144       goto error;
00145    }
00146    
00147    if ( recur_build_response_array(env, (&tree->node)->kids, &buf) != 0 ) {
00148       LM_ERR("failed to read from the MI tree!\n");
00149       xmlrpc_env_set_fault(env, 500, "Failed to write reply");
00150       goto error;
00151    }
00152 
00153    return 0;
00154 
00155 error:
00156    if ( reply_buffer ) pkg_free(reply_buffer);
00157    return -1;
00158 }
00159 
00160 static int recur_build_response( xmlrpc_env * env, struct mi_node * tree, str * buf )
00161 {
00162       for ( ; tree ; tree = tree->next ) {
00163       
00164       if ( xr_write_node( buf, tree ) != 0 ) {
00165       
00166          reply_buffer = (char*) pkg_realloc ( reply_buffer, 2*reply_buffer_len);
00167 
00168          if ( !reply_buffer ){
00169             LM_ERR("pkg_realloc cannot reallocate any more memory!\n");
00170             return -1;
00171          }
00172 
00173          buf->s = reply_buffer +(reply_buffer_len - buf->len);
00174          buf->len += reply_buffer_len;
00175          reply_buffer_len *=2 ;
00176 
00177          if ( xr_write_node( buf, tree ) != 0 ) {
00178             LM_ERR("failed to get MI node data!\n");
00179             return -1;
00180          }
00181       }
00182 
00183       if ( tree->kids ) {
00184          if ( recur_build_response(env, tree->kids, buf) != 0 )
00185             return -1;
00186       }
00187    }
00188 
00189    return 0;
00190 }
00191 
00192 char* xr_build_response( xmlrpc_env * env, struct mi_root * tree )
00193 {
00194    str buf;
00195    
00196    buf.s = reply_buffer;
00197    buf.len = reply_buffer_len;
00198 
00199    if ( tree->code<200 || tree->code>=300 ){
00200       LM_DBG("command processing failure: %s\n", tree->reason.s); 
00201       if (tree->reason.s)
00202          xmlrpc_env_set_fault(env, tree->code, tree->reason.s);
00203       else
00204          xmlrpc_env_set_fault(env, tree->code, "Error");
00205       return 0;
00206    }
00207    
00208    if ( recur_build_response(env, (&tree->node)->kids, &buf) != 0 ) {
00209       LM_ERR("failed to read from the MI tree!\n");
00210       xmlrpc_env_set_fault(env, 500, "Failed to build reply");
00211       return 0;
00212    }
00213    
00214    reply_buffer[reply_buffer_len-buf.len] = 0;
00215 
00216    return reply_buffer;
00217 }

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