Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief STRING buffer support
0003  *
0004  * @file typed_string.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 STRING_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 STRING_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[]="STRING_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 STRING_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[]="STRING_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_STRING)
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_STRING)
0142         {
0143             NDRX_LOG(log_info, "User buffer %s is different, "
0144                     "free it up and re-allocate as STRING", 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_STRING], 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 * STRING_tpalloc (typed_buffer_descr_t *descr, char *subtype, long *len)
0218 {
0219     char *ret;
0220 
0221     if (STRING_DEFAULT_SIZE > *len)
0222     {
0223         *len = STRING_DEFAULT_SIZE;
0224     }
0225 
0226     /* Allocate STRING buffer */
0227     ret=(char *)NDRX_MALLOC(*len);
0228     if (NULL!=ret)
0229     {
0230         ret[0] = EXEOS;
0231     }
0232     else
0233     {
0234         ndrx_TPset_error_fmt(TPEOS, "%s: Failed to allocate STRING buffer (len=%ld): %s",  
0235                 __func__, len, strerror(errno));
0236     }
0237     
0238 out:
0239     return ret;
0240 }
0241 
0242 /**
0243  * Re-allocate STRING buffer. Firstly we will find it in the list.
0244  * @param ptr
0245  * @param size
0246  * @return
0247  */
0248 expublic char * STRING_tprealloc(typed_buffer_descr_t *descr, char *cur_ptr, long len)
0249 {
0250     char *ret=NULL;
0251 
0252     if (0==len)
0253     {
0254         len = STRING_DEFAULT_SIZE;
0255     }
0256 
0257     /* Allocate STRING buffer */
0258     ret=(char *)NDRX_REALLOC(cur_ptr, len);
0259     
0260     if (NULL==ret)
0261     {
0262         ndrx_TPset_error_fmt(TPEOS, "%s: Failed to reallocate STRING buffer (len=%ld): %s",  
0263                 __func__, len, strerror(errno));
0264     }
0265 
0266     return ret;
0267 }
0268 
0269 /**
0270  * Gracefully remove free up the buffer
0271  * @param descr
0272  * @param buf
0273  */
0274 expublic void STRING_tpfree(typed_buffer_descr_t *descr, char *buf)
0275 {
0276     NDRX_FREE(buf);
0277 }
0278 
0279 /**
0280  * Check the expression on buffer.
0281  * @param descr
0282  * @param buf
0283  * @param expr
0284  * @return TRUE/FALSE.
0285  * In case of error we just return FALSE as not matched!
0286  */
0287 expublic int STRING_test(typed_buffer_descr_t *descr, char *buf, BFLDLEN len, char *expr)
0288 {
0289     int ret=EXFALSE;
0290     regex_t re; /* compiled regex */
0291     
0292     if (EXSUCCEED==(ret=regcomp(&re, expr, REG_EXTENDED | REG_NOSUB)))
0293     {
0294         if (EXSUCCEED==regexec(&re, buf, (size_t) 0, NULL, 0))
0295         {
0296             ret = EXTRUE;
0297         }
0298         regfree(&re);
0299     }
0300     else
0301     {
0302         NDRX_LOG(log_error, "Failed to compile regex event filter: [%s]", expr);
0303         userlog("Failed to compile regex event filter: [%s]", expr);
0304     }
0305     
0306     return ret;
0307 }
0308 
0309 
0310 /* vim: set ts=4 sw=4 et smartindent: */