Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Master Buffer serialization (aligned TLV of tags/len and XATMI buffers)
0003  *
0004  * @file pmultibuf.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 <sys/socket.h>
0037 #include <sys/time.h>
0038 #include <sys/types.h>
0039 #include <arpa/inet.h>
0040 #include <netinet/in.h>
0041 #include <errno.h>
0042 #include <fcntl.h>
0043 #include <netdb.h>
0044 #include <string.h>
0045 #include <unistd.h>
0046 #include <atmi.h>
0047 
0048 #include <stdio.h>
0049 #include <stdlib.h>
0050 
0051 #include <exnet.h>
0052 #include <ndrstandard.h>
0053 #include <ndebug.h>
0054 #include <ndrxdcmn.h>
0055 
0056 #include <utlist.h>
0057 #include <ubf_int.h>            /* FLOAT_RESOLUTION, DOUBLE_RESOLUTION */
0058 
0059 #include <typed_buf.h>
0060 #include <ubfutil.h>
0061 #include <math.h>
0062 #include <xatmi.h>
0063 #include <userlog.h>
0064 
0065 #include "fdatatype.h"
0066 #include <multibuf.h>
0067 #include "exnetproto.h"
0068 /*---------------------------Externs------------------------------------*/
0069 /*---------------------------Macros-------------------------------------*/
0070 /*---------------------------Enums--------------------------------------*/
0071 /*---------------------------Typedefs-----------------------------------*/
0072 /*---------------------------Statics------------------------------------*/
0073 /*---------------------------Prototypes---------------------------------*/
0074 
0075 /**
0076  * Loop over the master buffer,
0077  * this will emit the custom tags of MBUFs
0078  * 
0079  * @param fld Current proto field
0080  * @param level recursion level
0081  * @param offset offset in C struct (not to the field)
0082  * @param ex_buf start of the C struct ptr
0083  * @param ex_len C len
0084  * @param proto_buf output buffer
0085  * @param proto_buf_offset current offset at output buf
0086  * @param accept_tags which flags shall be generated in output
0087  * @param p_ub_data not used
0088  * @param proto_bufsz output buffer size
0089  * @return EXSUCCEED/EXFAIL
0090  */
0091 expublic int exproto_build_ex2proto_mbuf(cproto_t *fld, int level, long offset,
0092         char *ex_buf, long ex_len, char *proto_buf, long *proto_buf_offset,
0093         short *accept_tags, proto_ufb_fld_t *p_ub_data, 
0094         long proto_bufsz)
0095 {
0096     ndrx_mbuf_tlv_t *tlv_hdr;
0097     long tlv_pos;
0098     unsigned int tag_exp=0;
0099     int ret = EXSUCCEED;
0100     long *buf_len = (long *)(ex_buf+offset+fld->counter_offset);
0101     xmsg_t tmp_cv;
0102     long len_offset;
0103     long off_start;
0104     long off_stop;
0105     int len_written; /* The length we used  */
0106 
0107     memset(&tmp_cv, 0, sizeof(tmp_cv));
0108     
0109     /* write tag */
0110     if (EXSUCCEED!=ndrx_write_tag((short)fld->tag, proto_buf, 
0111             proto_buf_offset, proto_bufsz))
0112     {
0113         EXFAIL_OUT(ret);
0114     }
0115 
0116     NDRX_LOG(log_debug, "XINC tag: 0x%x (%s), current offset=%ld fld=%ld", 
0117             fld->tag, fld->cname, offset, offset+fld->offset);
0118 
0119     /* remember the TLV offset in protobuf  */
0120     len_offset = *proto_buf_offset;
0121     CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, LEN_BYTES);
0122     *proto_buf_offset=*proto_buf_offset+LEN_BYTES;
0123 
0124     off_start = *proto_buf_offset; 
0125     
0126     /* temp table */
0127     tmp_cv.descr="MBUF";
0128     tmp_cv.tabcnt=1;
0129     tmp_cv.tab[0] = ndrx_G_ndrx_mbuf_tlv_x;
0130 
0131     /* OK load the stuff ... */
0132     NDRX_LOG(log_debug, "** TLV START **");
0133     /* so from current position  till then current position + buffer len... */
0134     for (tlv_pos=offset+fld->offset; tlv_pos< (offset+fld->offset+*buf_len); 
0135             tlv_pos+=(ALIGNED_GEN(tlv_hdr->len)+sizeof(ndrx_mbuf_tlv_t)), tag_exp++)
0136     {
0137         int is_callinfo;
0138         unsigned int tag;
0139         int btype;
0140         
0141         tlv_hdr=(ndrx_mbuf_tlv_t *)(ex_buf + tlv_pos);
0142         
0143         tag = NDRX_MBUF_TAGTAG(tlv_hdr->tag);
0144         btype = NDRX_MBUF_TYPE(tlv_hdr->tag);
0145         is_callinfo = !!(tlv_hdr->tag & NDRX_MBUF_CALLINFOBIT);
0146         
0147         NDRX_LOG(log_debug, "Buffer tag: %u type: %d callinfo: %d len: %ld aligned: %d",
0148                 tag, btype, is_callinfo, tlv_hdr->len, ALIGNED_GEN(tlv_hdr->len));
0149         
0150         if (tag!=tag_exp)
0151         {
0152             NDRX_LOG(log_error, "ERROR: Expected tag %u but got %u", tag_exp, tag);
0153             return EXFAIL;
0154         }
0155         
0156         /* NDRX_DUMP(log_debug, "TAG data", tlv_hdr->data, tlv_hdr->len); */
0157         
0158         /* Write off the TLV to proto TLV */
0159         ret = exproto_build_ex2proto(&tmp_cv, 0, 
0160                 tlv_pos, /* < where the data starts*/
0161                 ex_buf, ex_len, proto_buf, proto_buf_offset,
0162                 accept_tags, p_ub_data, proto_bufsz);
0163         
0164         if (EXSUCCEED!=ret)
0165         {
0166             NDRX_LOG(log_error, "Failed to serialize multi-buf");
0167             EXFAIL_OUT(ret);
0168         }
0169     }
0170     
0171     
0172     /* write the len: (back to front) */
0173     off_stop = *proto_buf_offset;
0174     /* Put back len there.. */
0175     len_written = (int)(off_stop - off_start);
0176 
0177     NDRX_LOG(log_debug, "len_written=%d len_offset=%ld", 
0178             len_written, len_offset);
0179 
0180     if (EXSUCCEED!=ndrx_write_len(len_written, proto_buf, &len_offset, 
0181             proto_bufsz))
0182     {
0183         EXFAIL_OUT(ret);
0184     }
0185 
0186 out:
0187     NDRX_LOG(log_debug, "** TLV END %d **", ret);
0188             
0189     return ret;
0190 }
0191 
0192 /**
0193  * Convert multi-buffer to buffer from network to EX
0194  * Start to restore the TLV of the C, restore the TLV LEN
0195  * Restore TAG and start off the XATMI TLV DRIVER
0196  * @param fld Current conv field, this must be data
0197  * @param proto_buf protobuf ptr (data rcvd), current position in buf
0198  *  this points to our data. The data now again is our MBUF TLV in EXPROTO
0199  * @param proto_len buffer len (current tag len)
0200  * @param ex_buf Enduro/X output buffer C
0201  * @param ex_offset current offset in C (, updated to offset after data unload
0202  *  ptr. Also this means that dynamic field shall be last in C struct.
0203  * @param max_struct where we are currently. As
0204  * @param level recursion level
0205  * @param p_x_fb current UBF building (not used here)
0206  * @param p_ub_data UBF data (not used here)
0207  * @param ex_bufsz (Enduro/X output C buffer size)
0208  * @return EXSUCCED/EXFAIL
0209  */
0210 expublic int _exproto_proto2ex_mbuf(cproto_t *fld, char *proto_buf, long proto_len, 
0211         char *ex_buf, long ex_offset, long *max_struct, int level, 
0212         UBFH *p_x_fb, proto_ufb_fld_t *p_ub_data, long ex_bufsz)
0213 {
0214     
0215     /* got to de-serialize current tag.... (this is parent) */
0216     long *buf_len = (long *)(ex_buf+ex_offset+fld->counter_offset);
0217     unsigned step_size;
0218     unsigned ex_offset_dyn;
0219     int ret = EXSUCCEED;
0220     long int_pos=0;
0221     ndrx_mbuf_tlv_t *tlv_hdr=NULL;
0222     char *f_data_buf;
0223     ssize_t f_data_buf_len;
0224     proto_ufb_fld_t *f =  (proto_ufb_fld_t *)f_data_buf;
0225     int loop=0;
0226     NDRX_SYSBUF_MALLOC_OUT(f_data_buf, f_data_buf_len, ret);
0227     int trailing_align = 0;
0228     
0229     /* use cached len */
0230     /* bfldlen is current master buf offset, for several blocks.. */
0231     /*
0232      * The same C offset, yet nothing unloaded.
0233      * So here we need loop over... the proto_len
0234      * as there might be several buffers,
0235      * and each mbuf terminator is xatmi buf, which terminates the loop
0236      * within
0237      */
0238     do
0239     {
0240         loop++;
0241         ex_offset_dyn = ex_offset+fld->offset + p_ub_data->bfldlen;
0242         tlv_hdr =  (ndrx_mbuf_tlv_t *)(ex_buf+ex_offset_dyn);
0243 
0244         ret = _exproto_proto2ex(ndrx_G_ndrx_mbuf_tlv_x, proto_buf+int_pos, proto_len-int_pos, 
0245                 ex_buf, ex_offset_dyn, max_struct, 
0246                 0, NULL, NULL, ex_bufsz);
0247         
0248         if (EXFAIL==ret)
0249         {
0250             goto out;
0251         }
0252         
0253         int_pos+=ret;
0254         ret=EXSUCCEED;
0255         
0256         /* add the master-len value (i.e. increment the f and publish to  buf_len 
0257          * if the buffer was last, then we shall not count in the alignment
0258          */
0259         trailing_align = ALIGNED_GEN(tlv_hdr->len) - tlv_hdr->len;
0260         step_size=ALIGNED_GEN(tlv_hdr->len)+sizeof(ndrx_mbuf_tlv_t);
0261 
0262         /* we might get several calls here */
0263         p_ub_data->bfldlen+=step_size;
0264 
0265         /* update the call mater len */
0266         *buf_len= p_ub_data->bfldlen;
0267     
0268     } while (int_pos < proto_len);
0269     
0270     
0271     /* delete trailing alignment bytes */
0272     p_ub_data->bfldlen-=trailing_align;
0273     *buf_len-=trailing_align;
0274     
0275 out:
0276     
0277     /* free up the temp */
0278     if (NULL!=f_data_buf)
0279     {
0280         NDRX_SYSBUF_FREE(f_data_buf);
0281     }
0282     
0283     return ret;    
0284 }
0285 
0286 /* vim: set ts=4 sw=4 et smartindent: */