Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief JSON buffer support
0003  *
0004  * @file typed_json.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 #include <string.h>
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <memory.h>
0038 #include <errno.h>
0039 #include <utlist.h>
0040 
0041 #include <tperror.h>
0042 #include <ubf.h>
0043 #include <atmi.h>
0044 #include <typed_buf.h>
0045 #include <ndebug.h>
0046 #include <fdatatype.h>
0047 #include <userlog.h>
0048 /*---------------------------Externs------------------------------------*/
0049 /*---------------------------Macros-------------------------------------*/
0050 #define JSON_DEFAULT_SIZE    512
0051 /*---------------------------Enums--------------------------------------*/
0052 /*---------------------------Typedefs-----------------------------------*/
0053 /*---------------------------Globals------------------------------------*/
0054 /*---------------------------Statics------------------------------------*/
0055 /*---------------------------Prototypes---------------------------------*/
0056 /*
0057  * Prepare buffer for outgoing call/reply
0058  * idata - buffer data
0059  * ilen - data len (if needed)
0060  * obuf - place where to copy prepared buffer
0061  * olen - the actual lenght of data that should sent. Also this may represent
0062  *          space for the buffer to copy to.
0063  */
0064 expublic int JSON_prepare_outgoing (typed_buffer_descr_t *descr, char *idata, long ilen, 
0065                     char *obuf, long *olen, long flags)
0066 {
0067     int ret=EXSUCCEED;
0068     int str_used;
0069     char fn[]="JSON_prepare_outgoing";
0070     
0071     str_used = strlen(idata)+1; /* include EOS */
0072     
0073     /* Check that we have space enough to prepare for send */
0074     if (NULL!=olen && *olen < str_used)
0075     {
0076         ndrx_TPset_error_fmt(TPEINVAL, "%s: Internal buffer space: %d, "
0077                 "but requested: %d", fn, *olen, str_used);
0078         ret=EXFAIL;
0079         goto out;
0080     }
0081 
0082     memcpy(obuf, idata, str_used);
0083     
0084     /* return the actual length! */
0085     if (NULL!=olen)
0086         *olen = str_used;
0087     
0088 out:
0089     return ret;
0090 }
0091 
0092 /*
0093  * Prepare received buffer for internal processing.
0094  * May re-allocate the buffer.
0095  * rcv_data - received data buffer
0096  * odata - ptr to handler. Existing buffer may be reused or re-allocated
0097  * olen - output data length
0098  */
0099 expublic int JSON_prepare_incoming (typed_buffer_descr_t *descr, char *rcv_data, 
0100                         long rcv_len, char **odata, long *olen, long flags)
0101 {
0102     int ret=EXSUCCEED;
0103     int rcv_buf_size;
0104     int existing_size;
0105     
0106     char fn[]="JSON_prepare_incoming";
0107     buffer_obj_t *outbufobj=NULL;
0108 
0109     NDRX_LOG(log_debug, "Entering %s", fn);
0110     
0111     rcv_buf_size = strlen (rcv_data) + 1;
0112    
0113     
0114     /* Figure out the passed in buffer */
0115     if (NULL==(outbufobj=ndrx_find_buffer(*odata)))
0116     {
0117         ndrx_TPset_error_fmt(TPEINVAL, "Output buffer %p is not allocated "
0118                                         "with tpalloc()!", *odata);
0119         ret=EXFAIL;
0120         goto out;
0121     }
0122 
0123     /* Check the data types */
0124     if (NULL!=outbufobj)
0125     {
0126         /* If we cannot change the data type, then we trigger an error */
0127         if (flags & TPNOCHANGE && outbufobj->type_id!=BUF_TYPE_JSON)
0128         {
0129             /* Raise error! */
0130             ndrx_TPset_error_fmt(TPEOTYPE, "Receiver expects %s but got %s buffer",
0131                                         G_buf_descr[BUF_TYPE_NULL].type,
0132                                         G_buf_descr[outbufobj->type_id].type
0133                                         );
0134             ret=EXFAIL;
0135             goto out;
0136         }
0137         /* If we can change data type and this does not match, then
0138          * we should firstly free it up and then bellow allow to work in mode
0139          * when odata is NULL!
0140          */
0141         if (outbufobj->type_id!=BUF_TYPE_JSON)
0142         {
0143             NDRX_LOG(log_info, "User buffer %s is different, "
0144                     "free it up and re-allocate as JSON", G_buf_descr[outbufobj->type_id].type);
0145             ndrx_tpfree(*odata, outbufobj);
0146             *odata=NULL;
0147         }
0148     }
0149     
0150     /* check the output buffer */
0151     if (NULL!=*odata)
0152     {
0153         NDRX_LOG(log_debug, "%s: Output buffer exists", fn);
0154         
0155         existing_size = outbufobj->size;/*strlen(*odata) + 1;*/
0156         
0157 
0158         NDRX_LOG(log_debug, "%s: Output buffer size: %d, received %d", fn,
0159                             existing_size, rcv_buf_size);
0160         
0161         if (existing_size>=rcv_buf_size)
0162         {
0163             /* re-use existing buffer */
0164             NDRX_LOG(log_debug, "%s: Using existing buffer", fn);
0165         }
0166         else
0167         {
0168             /* Reallocate the buffer, because we have missing some space */
0169             char *new_addr;
0170             NDRX_LOG(log_debug, "%s: Reallocating", fn);
0171             
0172             if (NULL==(new_addr=ndrx_tprealloc(*odata, rcv_buf_size)))
0173             {
0174                 NDRX_LOG(log_error, "%s: _tprealloc failed!", fn);
0175                 ret=EXFAIL;
0176                 goto out;
0177             }
0178 
0179             /* allocated OK, return new address */
0180             *odata = new_addr;
0181         }
0182     }
0183     else
0184     {
0185         /* allocate the buffer */
0186         NDRX_LOG(log_debug, "%s: Incoming buffer where missing - "
0187                                          "allocating new!", fn);
0188 
0189         *odata = ndrx_tpalloc(&G_buf_descr[BUF_TYPE_JSON], NULL, NULL, rcv_len);
0190 
0191         if (NULL==*odata)
0192         {
0193             /* error should be set already */
0194             NDRX_LOG(log_error, "Failed to allocat new buffer!");
0195             goto out;
0196         }
0197     }
0198     
0199     /* Copy off the received data including EOS ofcorse. */
0200     strcpy(*odata, rcv_data);
0201     if (NULL!=olen)
0202     {
0203         *olen = rcv_len;
0204     }
0205     
0206 out:
0207     return ret;
0208 }
0209 
0210 /**
0211  * Allocate the buffer & register this into list, that we have such
0212  * List maintenance should be done by parent process tpalloc!
0213  * @param subtype
0214  * @param len
0215  * @return
0216  */
0217 expublic char * JSON_tpalloc (typed_buffer_descr_t *descr, char *subtype, long *len)
0218 {
0219     char *ret;
0220 
0221     if (JSON_DEFAULT_SIZE>*len)
0222     {
0223         *len = JSON_DEFAULT_SIZE;
0224     }
0225 
0226     /* Allocate JSON buffer */
0227     ret=(char *)NDRX_MALLOC(*len);
0228     
0229     if (NULL!=ret)
0230     {
0231         ret[0] = EXEOS;
0232     }
0233     else
0234     {        
0235         ndrx_TPset_error_fmt(TPEOS, "%s: Failed to allocate JSON buffer (len=%ld): %s",  
0236                 __func__, len, strerror(errno));
0237     }
0238     
0239 out:
0240     return ret;
0241 }
0242 
0243 /**
0244  * Re-allocate JSON buffer. Firstly we will find it in the list.
0245  * @param ptr
0246  * @param size
0247  * @return
0248  */
0249 expublic char * JSON_tprealloc(typed_buffer_descr_t *descr, char *cur_ptr, long len)
0250 {
0251     char *ret=NULL;
0252 
0253     if (0==len)
0254     {
0255         len = JSON_DEFAULT_SIZE;
0256     }
0257 
0258     /* Allocate JSON buffer */
0259     ret=(char *)NDRX_REALLOC(cur_ptr, len);
0260     
0261     if (NULL==ret)
0262     {
0263         ndrx_TPset_error_fmt(TPEOS, "%s: Failed to reallocate JSON buffer (len=%ld): %s",  
0264                 __func__, len, strerror(errno));
0265     }
0266 
0267     return ret;
0268 }
0269 
0270 /**
0271  * Gracefully remove free up the buffer
0272  * @param descr
0273  * @param buf
0274  */
0275 expublic void JSON_tpfree(typed_buffer_descr_t *descr, char *buf)
0276 {
0277     NDRX_FREE(buf);
0278 }
0279 
0280 /**
0281  * Check the expression on buffer.
0282  * @param descr
0283  * @param buf
0284  * @param expr
0285  * @return TRUE/FALSE.
0286  * In case of error we just return FALSE as not matched!
0287  */
0288 expublic int JSON_test(typed_buffer_descr_t *descr, char *buf, BFLDLEN len, char *expr)
0289 {
0290     int ret=EXFALSE;
0291     regex_t re; /* compiled regex */
0292     
0293     if (EXSUCCEED==(ret=regcomp(&re, expr, REG_EXTENDED | REG_NOSUB)))
0294     {
0295         if (EXSUCCEED==regexec(&re, buf, (size_t) 0, NULL, 0))
0296         {
0297             ret = EXTRUE;
0298         }
0299         regfree(&re);
0300     }
0301     else
0302     {
0303         NDRX_LOG(log_error, "Failed to compile regex event filter: [%s]", expr);
0304         userlog("Failed to compile regex event filter: [%s]", expr);
0305     }
0306     
0307     return ret;
0308 }
0309 
0310 
0311 /* vim: set ts=4 sw=4 et smartindent: */