Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief ATMI tpimport function implementation (Common version)
0003  *
0004  * @file tpimport.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 
0035 /*---------------------------Includes-----------------------------------*/
0036 #include <stdio.h>
0037 #include <stdarg.h>
0038 #include <memory.h>
0039 #include <stdlib.h>
0040 #include <errno.h>
0041 
0042 #include <atmi.h>
0043 #include <userlog.h>
0044 #include <ndebug.h>
0045 #include <tperror.h>
0046 #include <typed_buf.h>
0047 #include <atmi_int.h>
0048 
0049 #include <exparson.h>
0050 #include <view2exjson.h>
0051 #include <exbase64.h>
0052 /*---------------------------Externs------------------------------------*/
0053 /*---------------------------Macros-------------------------------------*/
0054 #define CARR_BUFFSIZE       NDRX_MSGSIZEMAX
0055 #define CARR_BUFFSIZE_B64   (4 * (CARR_BUFFSIZE) / 3)
0056 /*---------------------------Enums--------------------------------------*/
0057 /*---------------------------Typedefs-----------------------------------*/
0058 /*---------------------------Globals------------------------------------*/
0059 /*---------------------------Statics------------------------------------*/
0060 /*---------------------------Prototypes---------------------------------*/
0061 
0062 /**
0063  * NOTE That this will always if case of success, reallocate the buffer
0064  * to new node - that will be manual buffer. If original buf, was auto,
0065  * then it is not freed. If it was manual buffer, then tpfree is done on it.
0066  * BE AWARE!
0067  * @param bufctl
0068  * @param istr
0069  * @param ilen
0070  * @param obuf
0071  * @param olen
0072  * @param flags
0073  * @param parent_root_object if buffer is part of UBF buffer import
0074  * @return 
0075  */
0076 expublic int ndrx_tpimportex(ndrx_expbufctl_t *bufctl,
0077         char *istr, long ilen, char **obuf, long *olen, long flags,
0078         EXJSON_Object *parent_root_object)
0079 {
0080     int ret=EXSUCCEED;
0081     char *buftype;
0082     char buftype_obuf[XATMI_TYPE_LEN+1];
0083     char *subtype;
0084     char subtype_obuf[XATMI_SUBTYPE_LEN+1];
0085     double version;
0086     char *data;
0087     char *serialized_data=NULL;
0088     UBFH *p_ub=NULL;
0089     long size_used=EXFAIL;
0090     long size_existing=EXFAIL;
0091     long new_size=EXFAIL;
0092     char *obuftemp=NULL;
0093     char *istrtemp=NULL;
0094     size_t bufsz;
0095     int type;
0096     char *str_val;
0097     EXJSON_Value *root_value=NULL;
0098     EXJSON_Object *root_object=NULL;
0099     EXJSON_Value *data_value=NULL;
0100     EXJSON_Object *data_object=NULL;
0101 
0102     NDRX_LOG(log_debug, "%s: enter", __func__);
0103 
0104     if (NULL!=parent_root_object)
0105     {
0106         NDRX_LOG(log_debug, "Parsing from parent_root_object");
0107         root_object = parent_root_object;
0108     }
0109     else
0110     {
0111         bufsz = strlen(istr);
0112                 
0113         /* Check flag if base64 then decode from base64 */
0114         if ( TPEX_STRING == flags )
0115         {
0116             if (NULL==(istrtemp = NDRX_MALLOC(bufsz)))
0117             {
0118                 NDRX_LOG(log_error, "Failed to allocate %ld bytes", strlen(istr));
0119                 EXFAIL_OUT(ret);
0120             }
0121 
0122             if (NULL==ndrx_base64_decode(istr, strlen(istr), &bufsz, istrtemp))
0123             {
0124                 NDRX_LOG(log_error, "Failed to decode CARRAY");
0125                 EXFAIL_OUT(ret);
0126             }
0127             istrtemp[bufsz]=0;
0128         }
0129         else
0130         {
0131             istrtemp = istr;
0132         }
0133 
0134         NDRX_LOG(log_debug, "Parsing buffer: [%s] len =[%ld]", istrtemp, bufsz);
0135 
0136         if ( NULL == (root_value = exjson_parse_string_with_comments(istrtemp)))
0137         {
0138             NDRX_LOG(log_error, "Failed to parse istrtemp");
0139             EXFAIL_OUT(ret);
0140         }
0141         type = exjson_value_get_type(root_value);
0142         NDRX_LOG(log_info, "Type is %d", type);
0143 
0144         if (exjson_value_get_type(root_value) != EXJSONObject)
0145         {
0146             NDRX_LOG(log_error, "Failed to parse root element");
0147             ndrx_TPset_error_fmt(TPEINVAL, 
0148                                  "tpimport: Failed to parse json root element");
0149             EXFAIL_OUT(ret);
0150         }
0151 
0152         root_object = exjson_value_get_object(root_value);
0153     }
0154     
0155     if (NULL==(buftype = (char *)exjson_object_get_string(root_object, "buftype" )))
0156     {
0157         ndrx_TPset_error_fmt(TPEINVAL, 
0158                              "tpimport: missing buftype in input buffer");
0159         EXFAIL_OUT(ret);
0160     }
0161     if (NULL==(subtype = (char *)exjson_object_get_string(root_object, "subtype" )) &&
0162         0 == strcmp(BUF_TYPE_VIEW_STR, buftype))
0163     {
0164         ndrx_TPset_error_fmt(TPEINVAL, 
0165                              "tpimport: missing subtype for view");
0166         EXFAIL_OUT(ret);
0167     }
0168     if (0==(version = exjson_object_get_number(root_object, "version" )))
0169     {
0170         ndrx_TPset_error_fmt(TPEINVAL, 
0171                              "tpimport: missing version in input buffer");
0172         EXFAIL_OUT(ret);
0173     }
0174     
0175     if ( version<TPIMPEXP_VERSION_MIN || version>TPIMPEXP_VERSION_MAX )
0176     {
0177         ndrx_TPset_error_fmt(TPEINVAL, 
0178                              "tpimport: version, expected min version %d max %d",
0179                              TPIMPEXP_VERSION_MIN, TPIMPEXP_VERSION_MAX);
0180         EXFAIL_OUT(ret);
0181     }
0182     
0183     NDRX_LOG(log_debug, 
0184              "buftype: [%s] subtype: [%s] version: [%f]", 
0185              buftype, subtype?subtype:"null", version?version:0);
0186     
0187     if ( NULL != bufctl )
0188     {
0189         memset(bufctl, 0, sizeof(ndrx_expbufctl_t));
0190         NDRX_STRCPY_SAFE(bufctl->buftype, buftype);
0191         bufctl->buftype_ind = EXTRUE;
0192 
0193         bufctl->version = version;
0194         bufctl->version_ind = EXTRUE;
0195     }
0196 
0197     if (NULL!=*obuf)
0198     {
0199         if ( EXFAIL == (size_existing = ndrx_tptypes(*obuf, buftype_obuf, subtype_obuf)) )
0200         {
0201             NDRX_LOG(log_error, "Cannot determine buffer type");
0202             EXFAIL_OUT(ret);
0203         }
0204     }
0205     else
0206     {
0207         size_existing = EXFAIL;
0208     }
0209 
0210     /* check the import buffer type match with passed obuf
0211      if types changed and no change passed, then reject import */
0212     if ( (NULL!=*obuf) && TPEX_NOCHANGE == flags && 0!=(strcmp(buftype,buftype_obuf)) )
0213     {
0214         ndrx_TPset_error_fmt(TPEINVAL, 
0215                     "tpimport: import buffer type [%s] not match "
0216                     "with passed obuf type [%s]", buftype, buftype_obuf);
0217         EXFAIL_OUT(ret);
0218     }
0219     if ( 0==strcmp(BUF_TYPE_STRING_STR, buftype) )
0220     {
0221         if ( NULL == (obuftemp = ndrx_tpalloc(NULL, buftype, NULL, NDRX_MSGSIZEMAX)) )
0222         {
0223             NDRX_LOG(log_error, "Failed to allocate %s %ld bytes: %s", 
0224                      buftype, NDRX_MSGSIZEMAX, tpstrerror(tperrno));
0225             EXFAIL_OUT(ret);
0226         }
0227         if (NULL ==( data = (char *)exjson_object_get_string(root_object, "data" )) )
0228         {
0229             NDRX_LOG(log_error, "Failed get data for string import");
0230             EXFAIL_OUT(ret);
0231         }
0232         size_used = (long)strlen(data)+1;
0233         NDRX_STRCPY_SAFE_DST(obuftemp, data, NDRX_MSGSIZEMAX);
0234     }
0235     else if ( 0 == strcmp(BUF_TYPE_UBF_STR, buftype))
0236     {
0237         if ( NULL == (obuftemp = ndrx_tpalloc(NULL, buftype, NULL, NDRX_MSGSIZEMAX)) )
0238         {
0239             NDRX_LOG(log_error, "Failed to allocate %s %ld bytes: %s", 
0240                      buftype, NDRX_MSGSIZEMAX, tpstrerror(tperrno));
0241             EXFAIL_OUT(ret);
0242         }
0243         if (NULL == (data_object = exjson_object_get_object(root_object, "data" )) )
0244         {
0245             NDRX_LOG(log_error, "Failed get data for UBF import");
0246             EXFAIL_OUT(ret);
0247         }
0248         if ( EXSUCCEED!=ndrx_tpjsontoubf((UBFH *)obuftemp, NULL, data_object) )
0249         {
0250             NDRX_LOG(log_error, "Failed to import UBF buffer");
0251             EXFAIL_OUT(ret);
0252         }
0253         size_used = Bused((UBFH *)obuftemp);
0254     }
0255     else if ( 0 == strcmp(BUF_TYPE_VIEW_STR, buftype))
0256     {
0257         if (NULL == (data_object = exjson_object_get_object(root_object, "data" )) )
0258         {
0259             NDRX_LOG(log_error, "Failed get data for VIEW import");
0260             EXFAIL_OUT(ret);
0261         }
0262         obuftemp=ndrx_tpjsontoview(subtype, NULL, data_object, NULL);
0263         if ( NULL==obuftemp )
0264         {
0265             NDRX_LOG(log_error, "Failed to import VIEW");
0266             EXFAIL_OUT(ret);
0267         }
0268         size_used = Bvsizeof(subtype);
0269     }
0270     else if ( 0 == strcmp(BUF_TYPE_CARRAY_STR, buftype))
0271     {
0272         if ( NULL == (data = (char *)exjson_object_get_string(root_object, "data" )) )
0273         {
0274             NDRX_LOG(log_error, "Failed get data for CARRAY import");
0275             EXFAIL_OUT(ret);
0276         }
0277 
0278         if ( NULL == (obuftemp = ndrx_tpalloc(NULL, buftype, NULL, NDRX_MSGSIZEMAX)))
0279         {
0280             NDRX_LOG(log_error, "Failed to allocate carray buffer %ld bytes: %s",
0281                      (*olen), tpstrerror(tperrno));
0282             EXFAIL_OUT(ret);
0283         }
0284 
0285         if (NULL==ndrx_base64_decode(data, strlen(data), (size_t*)&size_used, obuftemp))
0286         {
0287             NDRX_LOG(log_error, "Failed to decode CARRAY");
0288             EXFAIL_OUT(ret);
0289         }
0290         new_size = size_existing=size_used;
0291     }
0292     else if ( 0 == strcmp(BUF_TYPE_JSON_STR, buftype))
0293     {
0294         if ( NULL == (obuftemp = ndrx_tpalloc(NULL, buftype, NULL, NDRX_MSGSIZEMAX)) )
0295         {
0296             NDRX_LOG(log_error, "Failed to allocate %s %ld bytes: %s", 
0297                      buftype, NDRX_MSGSIZEMAX, tpstrerror(tperrno));
0298             EXFAIL_OUT(ret);
0299         }
0300         if (NULL == (data_value = exjson_object_get_value(root_object, "data" )) )
0301         {
0302             NDRX_LOG(log_error, "Failed get data for JSON import");
0303             EXFAIL_OUT(ret);
0304         }
0305         if (exjson_value_get_type(data_value) != EXJSONObject)
0306         {
0307             NDRX_LOG(log_error, "Failed to parse data element");
0308             ndrx_TPset_error_fmt(TPEINVAL, 
0309                                  "tpimport: Failed to parse json data element");
0310             EXFAIL_OUT(ret);
0311         }
0312         serialized_data = exjson_serialize_to_string(data_value);
0313         size_used = (long)strlen(serialized_data)+1;
0314         NDRX_STRCPY_SAFE_DST(obuftemp, serialized_data, NDRX_MSGSIZEMAX);
0315     }
0316     else
0317     {
0318         EXFAIL_OUT(ret);
0319     }
0320     
0321     if (size_existing > size_used)
0322     {
0323         new_size = size_existing;
0324     }
0325     else if (size_existing < size_used)
0326     {
0327         new_size = size_used;
0328     }
0329     NDRX_LOG(log_debug, "new_size=[%ld] size_used=[%ld] size_existing=[%ld]",
0330          new_size, size_used, size_existing);
0331     
0332     if (EXFAIL!=new_size && NULL==(obuftemp = ndrx_tprealloc(obuftemp, new_size)))
0333     {
0334         EXFAIL_OUT(ret);
0335     }
0336 
0337     if (NULL!=olen)
0338     {
0339         *olen=new_size;
0340     }
0341     
0342     /* free up the but obuf if any */
0343     if ( NULL!=*obuf && !ndrx_tpisautobuf(*obuf) )
0344     {
0345         ndrx_tpfree(*obuf, NULL);
0346     }
0347     
0348     *obuf = obuftemp;
0349     
0350 out:
0351 
0352     /* cleanup code */
0353     if (NULL!=root_value)
0354     {
0355         exjson_value_free(root_value);
0356     }
0357 
0358     if (NULL != serialized_data)
0359     {
0360         exjson_free_serialized_string(serialized_data);
0361     }
0362     if ( TPEX_STRING == flags )
0363     {
0364         if (NULL!=istrtemp)
0365         {
0366             NDRX_FREE(istrtemp);
0367         }
0368     }
0369     NDRX_LOG(log_debug, "%s: return %d", __func__, ret);
0370 
0371     return ret;
0372 }
0373 /* vim: set ts=4 sw=4 et smartindent: */