Logo Search packages:      
Sourcecode: heartbeat-2 version File versions  Download package

cl_msg_types.c

/*
 * Heartbeat message type functions
 *
 * Copyright (C) 2004 Guochun Shi <gshi@ncsa.uiuc.edu>
 *
 * This software licensed under the GNU LGPL.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


#include <portability.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/utsname.h>
#include <ha_msg.h>
#include <unistd.h>
#include <clplumbing/cl_malloc.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/ipc.h>
#include <clplumbing/base64.h>
#include <clplumbing/netstring.h>
#include <glib.h>

#ifndef MAX
#     define MAX(a,b)   (((a) > (b)) ? (a) : (b))
#endif

#define NETSTRING_EXTRA(x) (intlen(x) + x + 2)

extern const char* FT_strings[];



#define           NL_TO_SYM   0
#define           SYM_TO_NL   1

int         SPECIAL_SYMS[]={
      20,
      21,
      22,
      23,
      24,
      25,
      26,
      27,
      28,
      29
};

#define            SPECIAL_SYM      19

struct ha_msg* string2msg_ll(const char*, size_t, int, int);
int compose_netstring(char*, const char*, const char*, size_t, size_t*);
int msg2netstring_buf(const struct ha_msg*, char*, size_t, size_t*);
int struct_display_print_spaces(char *buffer, int depth);
int struct_display_as_xml(int log_level, int depth, struct ha_msg *data,
                    const char *prefix, gboolean formatted);
int struct_stringlen(size_t namlen, size_t vallen, const void* value);
int struct_netstringlen(size_t namlen, size_t vallen, const void* value);
int   convert_nl_sym(char* s, int len, char sym, int direction);
 

static int
intlen(int x)
{
      char  buf[20];
      return snprintf(buf, sizeof(buf), "%d", x);
}


int
get_netstringlen(const struct ha_msg *m)
{
      int i;
      int total_len =0 ;
      
      if (m == NULL){
            cl_log(LOG_ERR, "get_netstringlen:"
                   "asking netstringlen of a NULL message");
            return 0;
      }
      
      total_len = sizeof(MSG_START_NETSTRING)
            + sizeof(MSG_END_NETSTRING) -2 ;
      
      
      for (i = 0; i < m->nfields; i++){         
            int len;
            len = fieldtypefuncs[m->types[i]].netstringlen(m->nlens[i], 
                                                 m->vlens[i],
                                                 m->values[i]);
            total_len += NETSTRING_EXTRA(len);
      }
      
      
      return total_len; 
      
      
}



int
get_stringlen(const struct ha_msg *m)
{
      int i;
      int total_len =0 ;

      if (m == NULL){
            cl_log(LOG_ERR, "get_stringlen:"
                   "asking stringlen of a NULL message");
            return 0;
      }
      
      for (i = 0; i < m->nfields; i++){         
            if (m->types[i] == FT_STRUCT){                  
                  total_len += struct_stringlen(m->nlens[i], 
                                          m->vlens[i],
                                          m->values[i]);
            }
      }
      
      total_len += m->stringlen;
      
      return total_len;
}



/*
  compute the total size of the resulted string
  if the string list is to be converted
  
*/
size_t
string_list_pack_length(const GList* _list)
{
      size_t i;
      GList* list = NULL;
      size_t total_length = 0;
      
      memcpy(&list, &_list, sizeof(GList*));
      (void)list;

      if (list == NULL){
            cl_log(LOG_WARNING, "string_list_pack_length():"
                   "list is NULL");

            return 0;
      }
      for (i = 0; i < g_list_length(list) ; i++){
            
            char * element = g_list_nth_data(list, i);
            if (element == NULL){
                  cl_log(LOG_ERR, "string_list_pack_length: "
                         "%luth element of the string list is NULL"
                        , (unsigned long)i);
                  return 0;
            }
            total_length += intlen(strlen(element)) + strlen(element) + 2;
            /* 2 is for ":" and "," */
            }
      return total_length ;
}



/*
  convert a string list into a single string
  the format to convert is similar to netstring:
      <length> ":" <the actual string> ","

  for example, a list containing two strings "abc" "defg"
  will be converted into
      3:abc,4:defg,
  @list: the list to be converted
  @buf:  the converted string should be put in the @buf
  @maxp: max pointer
*/


int
string_list_pack(GList* list, char* buf, char* maxp)
{
      size_t i;
      char* p =  buf;

      for (i = 0; i < g_list_length(list) ; i++){
            
            char * element = g_list_nth_data(list, i);
            int element_len = strlen(element);
            if (element == NULL){
                  cl_log(LOG_ERR, "string_list_pack: "
                         "%luth element of the string list is NULL"
                        , (unsigned long)i);
                  return 0;
            }
            p += sprintf(p, "%d:%s,", element_len,element);
            
            if (p >= maxp){
                  cl_log(LOG_ERR, "string_list_pack: "
                         "buffer overflowed ");
                  return 0;
            }           
      }
      
      
      return (p - buf);
}



/* 
   this is reverse process of pack_string_list
*/
GList* 
string_list_unpack(const char* packed_str_list, size_t length)
{
      GList*            list = NULL;
      const char* psl = packed_str_list;
      const char *      maxp= packed_str_list + length;
      int         len = 0;
      
      
      while(TRUE){
            char* buf;

            if (*psl == '\0' || psl >=  maxp){
                  break;
            }
            
            if (sscanf( psl, "%d:", &len) <= 0 ){
                  break;
            }
            
            if (len <=0){
                  cl_log(LOG_ERR, "unpack_string_list:"
                         "reading len of string error");
                  if (list){
                        list_cleanup(list);
                  }
                  return NULL;
            }
            
            while (*psl != ':' && *psl != '\0' ){
                  psl++;
            }
            
            if (*psl == '\0'){
                  break;
            }
            
            psl++;
            
            buf = ha_malloc(len + 1);
            if (buf == NULL){
                  cl_log(LOG_ERR, "unpack_string_list:"
                         "unable to allocate buf");
                  if(list){
                        list_cleanup(list);
                  }
                  return NULL;                  
                  
            }
            memcpy(buf, psl, len);
            buf[len] = '\0';
            list = g_list_append(list, buf);
            psl +=len;
            
            if (*psl != ','){
                  cl_log(LOG_ERR, "unpack_string_list:"
                         "wrong format, s=%s",packed_str_list);   
            }
            psl++;
      }
      
      return list;

}


static void
string_memfree(void* value)
{
      if (value){
            ha_free(value);
      }else {
            cl_log(LOG_ERR, "string_memfree: "
                   "value is NULL");
        }


      return;
}

static void
binary_memfree(void* value)
{
      string_memfree(value);
}


static void
struct_memfree( void* value)
{
      struct ha_msg* msg;

      if (!value){
            cl_log(LOG_ERR,
                   "value is NULL");
            return ;
      }
      
      msg = (struct ha_msg*) value;
      ha_msg_del(msg);
      return ;
}

static void
list_memfree(void* value)
{

      if (!value){
            cl_log(LOG_ERR,
                   "value is NULL");
            return ;
      }
      
      list_cleanup(value);    
      
}


static void* 
binary_dup(const void* value, size_t len)
{
      
      char* dupvalue;
      
      /* 0 byte binary field is allowed*/

      if (value == NULL && len > 0){
            cl_log(LOG_ERR, "binary_dup:"
                   "NULL value with non-zero len=%d", 
                   (int)len);
            return NULL;
      }
      
      dupvalue = ha_malloc(len + 1);
      if (dupvalue == NULL){
            cl_log(LOG_ERR, "binary_dup:"
                   "ha_malloc failed");
            return NULL;
      }
      
      if (value != NULL) {
            memcpy(dupvalue, value, len);
      }

      dupvalue[len] =0;
      
      return dupvalue;
}

static void*
string_dup(const void* value, size_t len)
{
      return binary_dup(value, len);
}


static void*
struct_dup(const void* value, size_t len)
{     
      char* dupvalue;
      
      (void)len;

      if (!value){
            cl_log(LOG_ERR,"struct_dup:"
                   "value is NULL");
            return NULL ;
      }
      
      
      dupvalue = (void*)ha_msg_copy((const struct ha_msg*)value);
      if (dupvalue == NULL){
            cl_log(LOG_ERR, "struct_dup: "
                   "ha_msg_copy failed");
            return NULL;
      }
      
      return dupvalue;
}

static GList* 
list_copy(const GList* _list)
{
      size_t i;
      GList* newlist = NULL;
      GList* list;

      memcpy(&list, &_list, sizeof(GList*));

      for (i = 0; i < g_list_length(list); i++){
            char* dup_element = NULL;
            char* element = g_list_nth_data(list, i);
            int len;
            if (element == NULL){
                  cl_log(LOG_WARNING, "list_cleanup:"
                         "element is NULL");
                  continue;
            }

            len = strlen(element);
            dup_element= ha_malloc(len + 1);
            if ( dup_element == NULL){
                  cl_log(LOG_ERR, "duplicate element failed");
                  continue;
            }
            memcpy(dup_element, element,len);
            dup_element[len] = 0;
            
            newlist = g_list_append(newlist, dup_element);        
      }
      
      return newlist;
}

static void*
list_dup( const void* value, size_t len)
{
      char* dupvalue;

      (void)len;
      if (!value){
            cl_log(LOG_ERR,"struct_dup:"
                   "value is NULL");
            return NULL ;
      }     
      
      dupvalue = (void*)list_copy((const GList*)value);
      
      if (!dupvalue){
            cl_log(LOG_ERR, "list_dup: "
                   "list_copy failed");
            return NULL;
      }
      
      return dupvalue;
}

static void
string_display(int log_level, int seq, char* name, void* value)
{
      HA_MSG_ASSERT(name);
      HA_MSG_ASSERT(value);
      cl_log(log_level, "MSG[%d] : [%s=%s]",
             seq, name, (const char*)value);
      return;
}

static void
binary_display(int log_level, int seq, char* name, void* value)
{
      HA_MSG_ASSERT(value);   
      HA_MSG_ASSERT(name);
      cl_log(log_level, "MSG[%d] : [(%s)%s=%p]",
             seq, FT_strings[FT_BINARY],
             name,      value);
}

static void
struct_display(int log_level, int seq, char* name, void* value)
{
      HA_MSG_ASSERT(name);
      HA_MSG_ASSERT(value);   
      cl_log(log_level, "MSG[%d] : [(%s)%s=%p]",
             seq, FT_strings[FT_STRUCT],
             name,      value);
      if(cl_get_string((struct ha_msg*) value, F_XML_TAGNAME) == NULL) {
            cl_log_message(log_level, (struct ha_msg*) value);
      } else {
            /* use a more friendly output format for nested messages */
            struct_display_as_xml(log_level, 0, value, NULL, TRUE);
      }
}

#define update_buffer_head(buffer, len) if(len < 0) { \
            (*buffer) = EOS; return -1;         \
      } else {                            \
            buffer += len;                      \
      }

int
struct_display_print_spaces(char *buffer, int depth) 
{
      int lpc = 0;
      int spaces = 2*depth;
      /* <= so that we always print 1 space - prevents problems with syslog */
      for(lpc = 0; lpc <= spaces; lpc++) {
            if(sprintf(buffer, "%c", ' ') < 1) {
                  return -1;
            }
            buffer += 1;
      }
      return lpc;
}

int
struct_display_as_xml(
      int log_level, int depth, struct ha_msg *data,
      const char *prefix, gboolean formatted) 
{
      int lpc = 0;
      int printed = 0;
      gboolean has_children = FALSE;
      char print_buffer[1000];
      char *buffer = print_buffer;
      const char *name = cl_get_string(data, F_XML_TAGNAME);

      if(data == NULL) {
            return 0;

      } else if(name == NULL) {
            cl_log(LOG_WARNING, "Struct at depth %d had no name", depth);
            cl_log_message(log_level, data);
            return 0;
      }
      
      if(formatted) {
            printed = struct_display_print_spaces(buffer, depth);
            update_buffer_head(buffer, printed);
      }
      
      printed = sprintf(buffer, "<%s", name);
      update_buffer_head(buffer, printed);
      
      for (lpc = 0; lpc < data->nfields; lpc++) {
            const char *prop_name = data->names[lpc];
            const char *prop_value = data->values[lpc];
            if(data->types[lpc] != FT_STRING) {
                  continue;
            } else if(prop_name == NULL) {
                  continue;
                  
            /* hide the next two */
            } else if(strcmp(F_XML_TAGNAME, prop_name) == 0) {
                  continue;
            } else if(strcmp(F_XML_PARENT, prop_name) == 0) {
                  continue;
            }
            printed = sprintf(buffer, " %s=\"%s\"", prop_name, prop_value);
            update_buffer_head(buffer, printed);
      }

      for (lpc = 0; lpc < data->nfields; lpc++) {
            if(data->types[lpc] == FT_STRUCT) {
                  has_children = TRUE;
                  break;
            }
      }

      printed = sprintf(buffer, "%s>", has_children==0?"/":"");
      update_buffer_head(buffer, printed);
      cl_log(log_level, "%s%s", prefix?prefix:"", print_buffer);
      buffer = print_buffer;
      
      if(has_children == FALSE) {
            return 0;
      }
      
      for (lpc = 0; lpc < data->nfields; lpc++) {
            if(data->types[lpc] != FT_STRUCT) {
                  continue;
            } else if(0 > struct_display_as_xml(
                          log_level, depth+1, data->values[lpc],
                          prefix, formatted)) {
                  return -1;
            }
      }

      if(formatted) {
            printed = struct_display_print_spaces(buffer, depth);
            update_buffer_head(buffer, printed);
      }
      cl_log(log_level, "%s%s</%s>", prefix?prefix:"", print_buffer, name);

      return 0;
}




static int 
liststring(GList* list, char* buf, int maxlen)
{
      char* p = buf;
      char* maxp = buf + maxlen;
      size_t i;
      
      for ( i = 0; i < g_list_length(list); i++){
            char* element = g_list_nth_data(list, i);
            if (element == NULL) {
                  cl_log(LOG_ERR, "%luth element is NULL "
                  ,     (unsigned long)i);
                  return HA_FAIL;
            } else{
                  if (i == 0){
                        p += sprintf(p,"%s",element);
                  }else{
                        p += sprintf(p," %s",element);
                  }
                  
            }
            if ( p >= maxp){
                  cl_log(LOG_ERR, "buffer overflow");
                  return HA_FAIL;
            }
            
      }
      
      return HA_OK;
}

static void
list_display(int log_level, int seq, char* name, void* value)
{
      GList* list;
      char buf[MAXLENGTH];
      
      HA_MSG_ASSERT(name);
      HA_MSG_ASSERT(value);

      list = value;

      if (liststring(list, buf, MAXLENGTH) != HA_OK){
            cl_log(LOG_ERR, "liststring error");
            return;
      }
      cl_log(log_level, "MSG[%d] :[(%s)%s=%s]",
             seq, FT_strings[FT_LIST],
             name, buf);                  
      
      return ;
      
}


/*
 * This function changes each new line in the input string
 * into a special symbol, or the other way around
 */

int
convert_nl_sym(char* s, int len, char sym, int direction)
{
      int   i;

      if (direction != NL_TO_SYM && direction != SYM_TO_NL){
            cl_log(LOG_ERR, "convert_nl_sym(): direction not defined!");
            return(HA_FAIL);
      }


      for (i = 0; i < len && s[i] != EOS; i++){
            
            switch(direction){
            case NL_TO_SYM :
                  if (s[i] == '\n'){
                        s[i] = sym;
                        break;
                  }

                  if (s[i] == sym){
                        cl_log(LOG_ERR
                        , "convert_nl_sym(): special symbol \'0x%x\' found"
                        " in string at %d (len=%d)", s[i], i, len);
                        return(HA_FAIL);
                  }

                  break;

            case SYM_TO_NL:
                                    
                  if (s[i] == sym){
                        s[i] = '\n';
                        break;
                  }
                  break;
            default:
                  /* nothing, never executed*/;
                  
            }
      }
      
      return(HA_OK);
}


/*
 * This function changes each new line in the input string
 * into a special symbol, or the other way around
 */

static int
convert(char* s, int len, int depth, int direction)
{
      
      if (direction != NL_TO_SYM && direction != SYM_TO_NL){
            cl_log(LOG_ERR, "convert(): direction not defined!");
            return(HA_FAIL);
      }
      
      
      if (depth >= MAXDEPTH ){
            cl_log(LOG_ERR, "convert(): MAXDEPTH exceeded");
            return(HA_FAIL);
      }
      
      return convert_nl_sym(s, len, SPECIAL_SYMS[depth], direction);
}




static int 
string_stringlen(size_t namlen, size_t vallen, const void* value)
{
      
      HA_MSG_ASSERT(value);
      HA_MSG_ASSERT( vallen == strlen(value));
      return namlen + vallen+ 2;
}

static int
binary_netstringlen(size_t namlen, size_t vallen, const void* value)
{
      int   length;
      
      HA_MSG_ASSERT(value);
      
      length = 3 + namlen + 1 + vallen;
      
      return length;
}


static int 
string_netstringlen(size_t namlen, size_t vallen, const void* value)
{
      HA_MSG_ASSERT(value);
      HA_MSG_ASSERT( vallen == strlen(value));
      
      return binary_netstringlen(namlen, vallen, value);
}


static int
binary_stringlen(size_t namlen, size_t vallen, const void* value)
{
      HA_MSG_ASSERT(value);

      return namlen + B64_stringlen(vallen)  + 2 + 3;
      /*overhead 3 is for type*/    
}





int
struct_stringlen(size_t namlen, size_t vallen, const void* value)
{
      const struct ha_msg* childmsg;
      
      HA_MSG_ASSERT(value);
      
      (void)vallen;
      childmsg = (const struct ha_msg*)value;
      
      return namlen +2 + 3 + get_stringlen(childmsg); 
      /*overhead 3 is for type*/
}

int
struct_netstringlen(size_t namlen, size_t vallen, const void* value)
{

      int ret;
      const struct ha_msg* childmsg;
      int len;

      HA_MSG_ASSERT(value);   

      (void)vallen;
      childmsg = (const struct ha_msg*)value;
      
      len = get_netstringlen(childmsg);

      ret = 3 + namlen + 1 + len;

      return ret;
      
}


static int
list_stringlen(size_t namlen, size_t vallen, const void* value)
{
      (void)value;
      return namlen + vallen + 2 + 3;     
      /*overhead 3 is for type (FT_STRUCT)*/
}

static int
list_netstringlen(size_t namlen, size_t vallen, const void* value)
{
      int ret;
      const GList* list;
      
      list = (const GList*)value;
      
      ret =  3 + namlen + 1 + string_list_pack_length(list);
      
      return ret;

}

static int 
add_binary_field(struct ha_msg* msg, char* name, size_t namelen,
             void* value, size_t vallen, int depth)
{

      int next;

      if ( !msg || !name || !value
           || depth < 0){
            cl_log(LOG_ERR, "add_binary_field:"
                   " invalid input argument");
            return HA_FAIL;
      }
            

      next = msg->nfields;
      msg->names[next] = name;
      msg->nlens[next] = namelen;
      msg->values[next] = value;
      msg->vlens[next] = vallen;
      
      msg->stringlen += binary_stringlen(namelen, vallen, value);
      
      msg->types[next] = FT_BINARY;
      msg->nfields++;   
      
      return HA_OK;
}


static int 
add_struct_field(struct ha_msg* msg, char* name, size_t namelen,
             void* value, size_t vallen, int depth)
{     
      int next;
      struct ha_msg* childmsg;

      if ( !msg || !name || !value
           || depth < 0){
            cl_log(LOG_ERR, "add_struct_field:"
                   " invalid input argument");
            return HA_FAIL;
      }
      
      childmsg = (struct ha_msg*)value; 
      
      next = msg->nfields;
      msg->names[next] = name;
      msg->nlens[next] = namelen;
      msg->values[next] = value;
      msg->vlens[next] = vallen;                
      msg->types[next] = FT_STRUCT;
      
      msg->nfields++;   
      
      return HA_OK;
}




static int 
add_list_field(struct ha_msg* msg, char* name, size_t namelen,
             void* value, size_t vallen, int depth)
{
      int next;
      int j;
      GList* list = NULL;
      int stringlen_add;

      if ( !msg || !name || !value
           || namelen <= 0 
           || vallen <= 0
           || depth < 0){
            cl_log(LOG_ERR, "add_list_field:"
                   " invalid input argument");
            return HA_FAIL;
      }
      
      
      for (j=0; j < msg->nfields; ++j) {
            if (strcmp(name, msg->names[j]) == 0) {
                  break;
            }
      }
      
      if ( j >= msg->nfields){
            int listlen;
            list = (GList*)value;

            listlen = string_list_pack_length(list);

            stringlen_add = list_stringlen(namelen,listlen , value);
            
            next = msg->nfields;
            msg->names[next] = name;
            msg->nlens[next] = namelen;
            msg->values[next] = value;
            msg->vlens[next] =  vallen;
            msg->types[next] = FT_LIST;
            msg->stringlen += stringlen_add;
            msg->nfields++;
            
      }  else if(  msg->types[j] == FT_LIST ){

            GList* oldlist = (GList*) msg->values[j];
            int oldlistlen = string_list_pack_length(oldlist);
            int newlistlen;
            size_t i; 
            
            for ( i =0; i < g_list_length((GList*)value); i++){
                  list = g_list_append(oldlist, g_list_nth_data((GList*)value, i));
            }
            if (list == NULL){
                  cl_log(LOG_ERR, "add_list_field:"
                         " g_list_append() failed");
                  return HA_FAIL;
            }
            
            newlistlen = string_list_pack_length(list);           
            
            stringlen_add = newlistlen - oldlistlen;

            msg->values[j] = list;
            msg->vlens[j] =  string_list_pack_length(list);
            msg->stringlen +=  stringlen_add;
            g_list_free((GList*)value); /*we don't free each element
                                    because they are used in new list*/
            
      } else { 
            cl_log(LOG_ERR, "field already exists "
                   "with differnt type=%d", msg->types[j]);
            return (HA_FAIL);
      }
            
      return HA_OK;
}



/*print a string to a string,
  pretty simple one :)
*/
static int
str2string(char* buf, char* maxp, void* value, size_t len, int depth)
{
      char* s =  value;
      char* p = buf;
      (void)maxp;
      (void)depth;
      if ( strlen(s) != len){
            cl_log(LOG_ERR, "str2string:"
                   "the input len != string length");
            return -1;
      }
      
      strcat(buf, s);
      while(*p != '\0'){
            if (*p == '\n'){
                  *p = SPECIAL_SYM;
            }
            p++;
      }

      return len;
      
}

/*print a binary value to a string using base64
  library 
*/

static int
binary2string(char* buf, char* maxp, void* value, size_t len, int depth)
{
      int baselen;
      int truelen = 0;
      
      (void)depth;
      baselen = B64_stringlen(len) + 1;
      
      if ( buf + baselen >= maxp){
            cl_log(LOG_ERR, "binary2string: out of bounary");
            return -1;
      }
      
      truelen = binary_to_base64(value, len, buf, baselen);
      
      return truelen;
}

/*print a struct(ha_msg) to a string            
  @depth denotes the number of recursion
*/

static int
struct2string(char* buf, char* maxp, void* value, size_t len, int depth)
{

      struct ha_msg* msg = value;
      int   baselen = get_stringlen(msg);
      
      (void)len;

      if ( buf + baselen > maxp){
            cl_log(LOG_ERR, "struct2string: not enough buffer"
                   "for the struct to generate a string");
            return -1;
      }

      if (msg2string_buf(msg, buf ,baselen,depth + 1, NEEDHEAD)
          != HA_OK){
            
            cl_log(LOG_ERR
                   , "struct2string(): msg2string_buf for"
                   " child message failed");          
            return -1;
            
      }
      
      if (convert(buf, baselen, depth, NL_TO_SYM) != HA_OK){            
            cl_log(LOG_ERR , "struct2string(): convert failed");        
            return -1;        
      }
      
      return strlen(buf);
}




/* print a list to a string
 */

static int
list2string(char* buf, char* maxp, void* value, size_t len, int depth)
{
      int listlen;
      GList* list = (GList*) value;

      (void)len;
      (void)depth;
      listlen = string_list_pack(list , buf, maxp);               
      if (listlen == 0){
            cl_log(LOG_ERR, "list2string():"
                   "string_list_pack() failed");
            return -1;
      }
      
      return listlen;   
      
}


static int
string2str(void* value, size_t len, int depth, void** nv, size_t* nlen )
{
      if (!value  || !nv || !nlen || depth < 0){
            cl_log(LOG_ERR, "string2str:invalid input");
            return HA_FAIL;
      }
      
      if (convert_nl_sym(value, len, SPECIAL_SYM, SYM_TO_NL) !=  HA_OK){
            cl_log(LOG_ERR, "string2str:convert_nl_sym"
                   "from symbol to new line failed");
            return HA_FAIL;
      }
      *nv = value;
      *nlen = len;
      
      return HA_OK;
}

static int
string2binary(void* value, size_t len, int depth, void** nv, size_t* nlen)
{
      char  tmpbuf[MAXMSG];

      if (value == NULL && len == 0){
            *nv = NULL;
            *nlen = 0;
            return HA_OK;
      }

      if ( !value || !nv || depth < 0){
            cl_log(LOG_ERR, "string2binary:invalid input");
            return HA_FAIL;
      }
      
      memcpy(tmpbuf, value, len);
      *nlen = base64_to_binary(tmpbuf, len, value, len);                      
      
      *nv = value;
      
      return HA_OK;
}

static int
string2struct(void* value, size_t vallen, int depth, void** nv, size_t* nlen)
{
      
      struct ha_msg     *tmpmsg;

      if (!value || !nv || depth < 0){
            cl_log(LOG_ERR, "string2struct:invalid input");
            return HA_FAIL;
      }
      
      
      if (convert(value, vallen, depth,SYM_TO_NL) != HA_OK){
            cl_log(LOG_ERR
                   ,    "ha_msg_addraw_ll(): convert failed");
            return(HA_FAIL);
      }
      
      tmpmsg = string2msg_ll(value, vallen,depth + 1, 0);
      if (tmpmsg == NULL){
            cl_log(LOG_ERR
                   ,    "string2struct()"
                   ": string2msg_ll failed");
            return(HA_FAIL);
      }
      ha_free(value);
      *nv = tmpmsg;
      *nlen = 0;
      
      return HA_OK;

}

static int
string2list(void* value, size_t vallen, int depth, void** nv, size_t* nlen)
{
      GList*      list;
      
      if (!value  || !nv || !nlen || depth < 0){
            cl_log(LOG_ERR, "string2struct:invalid input");
            return HA_FAIL;
      }     
      
      list = string_list_unpack(value, vallen);
      if (list == NULL){
            cl_log(LOG_ERR, "ha_msg_addraw_ll():"
                   "unpack_string_list failed: %s", (char*)value);
            return(HA_FAIL);
      }
      ha_free(value);
      
      *nv = (void*)list;
      *nlen = string_list_pack_length(list);
      
      return HA_OK;

}

static int
fields2netstring(char* sp, char* smax, char* name, size_t nlen,
             void* value, size_t vallen, int type, size_t* comlen)
{
      size_t fieldlen;
      size_t slen;
      int ret = HA_OK;
      char* sp_save = sp;

      fieldlen = fieldtypefuncs[type].netstringlen(nlen, vallen, value);
      if (fieldlen > MAXMSG){
            cl_log(LOG_INFO, "field too big(%d)", (int)fieldlen);
            return HA_FAIL;
      }
      sp += sprintf(sp , "%d:(%d)%s=", (int)fieldlen, type, name);
      switch (type){

      case FT_STRING:
      case FT_BINARY:
            memcpy(sp, value, vallen);
            slen = vallen;
            break;

      case FT_STRUCT:
            {
                  struct ha_msg* msg = (struct ha_msg*) value;
                  ret = msg2netstring_buf(msg, sp,get_netstringlen(msg),
                                    &slen);
                  break;
            }
      case FT_LIST:
            {

                  char buf[MAXLENGTH];
                  GList* list = NULL;
                  int tmplen;
                  
                  list = (GList*) value;
                  
                  tmplen = string_list_pack_length(list);
                  if (tmplen >= MAXLENGTH){
                        cl_log(LOG_ERR,
                               "string list length exceeds limit");
                        return(HA_FAIL);
                  }
                  
                  if (string_list_pack(list, buf, buf + MAXLENGTH) 
                      != tmplen ){
                        cl_log(LOG_ERR, 
                               "packing string list return wrong length");
                        return(HA_FAIL);
                  }
                  
                  
                  memcpy(sp, buf, tmplen);
                  slen = tmplen;
                  ret = HA_OK;
                  break;
            }
            
      default:
            ret = HA_FAIL;
            cl_log(LOG_ERR, "%s: Wrong type (%d)", __FUNCTION__,type);
      }     

      if (ret == HA_FAIL){
            return ret;
      }
      
      sp +=slen;
      *sp++ = ',';
      *comlen = sp - sp_save;
      
      return HA_OK;
      
      
}


static int
netstring2string(const void* value, size_t vlen, void** retvalue, size_t* ret_vlen)
{
      char* dupvalue;
      
      if (value == NULL && vlen == 0){
            *retvalue = NULL;
            *ret_vlen = 0;
            return HA_OK;
      }

      if ( !value || !retvalue || !ret_vlen){
            cl_log(LOG_ERR, " netstring2string:"
                   "invalid input arguments");
            return HA_FAIL;
      }
      
      dupvalue = string_dup(value, vlen);
      if (!dupvalue){
            cl_log(LOG_ERR, "netstring2string:"
                   "duplicating value failed");
            return HA_FAIL;
      }
      
      *retvalue = dupvalue;
      *ret_vlen = vlen;
      
      return HA_OK;
}

static int
netstring2binary(const void* value, size_t vlen, void** retvalue, size_t* ret_vlen)
{
      return netstring2string(value, vlen, retvalue, ret_vlen);
      
}

static int
netstring2struct(const void* value, size_t vlen, void** retvalue, size_t* ret_vlen)
{
      struct ha_msg* msg;
      
      if ( !value || !retvalue || !ret_vlen){
            cl_log(LOG_ERR, " netstring2struct:"
                   "invalid input arguments");
            return HA_FAIL;
      }     
      
      msg =  netstring2msg(value, vlen, 0);
      if (!msg){
            cl_log(LOG_ERR, "netstring2struct:"
                   "netstring2msg failed");
            return HA_FAIL;
      }
      
      *retvalue =(void* ) msg;
      *ret_vlen = 0;
      
      return HA_OK;
      
}

static int
netstring2list(const void* value, size_t vlen, void** retvalue, size_t* ret_vlen)
{     
      GList* list;
      
      if ( !value || !retvalue || !ret_vlen){
            cl_log(LOG_ERR, " netstring2struct:"
                   "invalid input arguments");
            return HA_FAIL;
      }     
      
      
      list = string_list_unpack(value, vlen);
      if (list == NULL){
            cl_log(LOG_ERR, "netstring2list: unpacking string list failed");
            cl_log(LOG_INFO, "thisbuf=%s", (const char*)value);
            return HA_FAIL;
      }
      *retvalue = (void*)list;
      
      *ret_vlen = string_list_pack_length(list);
      
      return HA_OK;
      
}





static int 
add_string_field(struct ha_msg* msg, char* name, size_t namelen,
             void* value, size_t vallen, int depth)
{
      
      size_t      internal_type;
      unsigned long     tmptype;
      char  *cp_name = NULL;
      size_t      cp_namelen;
      size_t      cp_vallen;
      void  *cp_value = NULL;
      int   next;
      int   stringlen_add = 0 ;

      if ( !msg || !name || !value
           || namelen <= 0 
           || depth < 0){
            cl_log(LOG_ERR, "add_string_field:"
                   " invalid input argument");
            return HA_FAIL;
      }
      

      
      internal_type = FT_STRING;
      if (name[0] == '('){

            int   nlo = 3; /*name length overhead */
            if (name[2] != ')'){
                  if (!cl_msg_quiet_fmterr) {
                        cl_log(LOG_ERR
                               , "ha_msg_addraw_ll(): no closing parentheses");
                  }
                  return(HA_FAIL);
            }
            if (sscanf(name + 1, "%lu", &tmptype) <= 0) {
                  cl_log(LOG_ERR
                         ,    "ha_msg_addraw_ll(): not a number.");
                  return(HA_FAIL);
            }

            internal_type = tmptype;
            
            if (internal_type ==  FT_STRING){
                  cl_log(LOG_ERR
                         ,    "ha_msg_addraw_ll(): wrong type");
                  return(HA_FAIL);
            }

            cp_name = name;
            cp_namelen = namelen - nlo ;
            memmove(cp_name, name + nlo, namelen - nlo);
            cp_name[namelen - nlo] = EOS;
      }else {
            cp_name = name;
            cp_namelen = namelen;   
            
      }
      
      if(internal_type  < DIMOF(fieldtypefuncs)){
            int (*stringtofield)(void*, size_t, int depth, void**, size_t* );
            int (*fieldstringlen)( size_t, size_t, const void*);

            stringtofield= fieldtypefuncs[internal_type].stringtofield;
            
            if (!stringtofield || stringtofield(value, vallen, depth, &cp_value, &cp_vallen) != HA_OK){
                  cl_log(LOG_ERR, "add_string_field: stringtofield failed");
                  return HA_FAIL;
            }
            
            fieldstringlen = fieldtypefuncs[internal_type].stringlen;
            if (!fieldstringlen || (stringlen_add = 
                              fieldstringlen(cp_namelen, cp_vallen, cp_value)) <= 0 ){
                  
                  cl_log(LOG_ERR, "add_string_field: stringlen failed");
                  return HA_FAIL;
            }
            
      } else {
            cl_log(LOG_ERR, "add_string_field():"
                   " wrong type %lu", (unsigned long)internal_type);
            return HA_FAIL;
      }
      
      
      next = msg->nfields;
      msg->values[next] = cp_value;
      msg->vlens[next] = cp_vallen;
      msg->names[next] = cp_name;
      msg->nlens[next] = cp_namelen;
      
      if (internal_type != FT_STRUCT){
            msg->stringlen += stringlen_add;    
      }
      
      msg->types[next] = internal_type;
      msg->nfields++;
      
      return HA_OK;
      
}



struct fieldtypefuncs_s fieldtypefuncs[4]=
      { {string_memfree, string_dup, string_display, add_string_field, 
         string_stringlen,string_netstringlen, str2string,fields2netstring, string2str, netstring2string},
        
        {binary_memfree, binary_dup, binary_display, add_binary_field,
         binary_stringlen,binary_netstringlen, binary2string,fields2netstring, string2binary, netstring2binary},
        
        {struct_memfree, struct_dup, struct_display, add_struct_field, 
         struct_stringlen, struct_netstringlen, struct2string, fields2netstring, string2struct, netstring2struct},
        
        {list_memfree, list_dup, list_display, add_list_field, 
         list_stringlen, list_netstringlen, list2string, fields2netstring, string2list, netstring2list},
      };



Generated by  Doxygen 1.6.0   Back to index