Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief EnduroX cluster protocol.
0003  *   TLV will be simple structure:
0004  *   Tag: 2 bytes
0005  *   Length: 2 bytes
0006  *   Data...
0007  *   All data will be generated as ASCII chars.
0008  *
0009  * @file proto.c
0010  */
0011 /* -----------------------------------------------------------------------------
0012  * Enduro/X Middleware Platform for Distributed Transaction Processing
0013  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0014  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0015  * This software is released under one of the following licenses:
0016  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0017  * See LICENSE file for full text.
0018  * -----------------------------------------------------------------------------
0019  * AGPL license:
0020  *
0021  * This program is free software; you can redistribute it and/or modify it under
0022  * the terms of the GNU Affero General Public License, version 3 as published
0023  * by the Free Software Foundation;
0024  *
0025  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0026  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0027  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0028  * for more details.
0029  *
0030  * You should have received a copy of the GNU Affero General Public License along 
0031  * with this program; if not, write to the Free Software Foundation, Inc.,
0032  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0033  *
0034  * -----------------------------------------------------------------------------
0035  * A commercial use license is available from Mavimax, Ltd
0036  * contact@mavimax.com
0037  * -----------------------------------------------------------------------------
0038  */
0039 
0040 /*---------------------------Includes-----------------------------------*/
0041 #include <sys/socket.h>
0042 #include <sys/time.h>
0043 #include <sys/types.h>
0044 #include <arpa/inet.h>
0045 #include <netinet/in.h>
0046 #include <errno.h>
0047 #include <fcntl.h>
0048 #include <netdb.h>
0049 #include <string.h>
0050 #include <unistd.h>
0051 #include <atmi.h>
0052 
0053 #include <stdio.h>
0054 #include <stdlib.h>
0055 
0056 #include <exnet.h>
0057 #include <ndrstandard.h>
0058 #include <ndebug.h>
0059 #include <ndrxdcmn.h>
0060 
0061 #include <utlist.h>
0062 #include <ubf_int.h>            /* FLOAT_RESOLUTION, DOUBLE_RESOLUTION */
0063 
0064 #include <typed_buf.h>
0065 #include <ubfutil.h>
0066 #include <math.h>
0067 #include <xatmi.h>
0068 #include <userlog.h>
0069 #include <multibuf.h>
0070 
0071 #include "fdatatype.h"
0072 #include "exnetproto.h"
0073 #include "ubfview.h"
0074 
0075 /*---------------------------Externs------------------------------------*/
0076 /*---------------------------Macros-------------------------------------*/
0077 /*---------------------------Enums--------------------------------------*/
0078 /*---------------------------Typedefs-----------------------------------*/
0079 /*---------------------------Globals------------------------------------*/
0080 
0081 exprivate xmsg_t * classify_netcall (char *ex_buf, long ex_len);
0082 
0083 /* Type dscription, for debugging */
0084 static char *M_type[] = {
0085 "EXF_SHORT",    /* 0 */
0086 "EXF_LONG",     /* 1 */
0087 "EXF_CHAR",     /* 2 */
0088 "EXF_FLOAT",    /* 3 */
0089 "EXF_DOUBLE",   /* 4 */
0090 "EXF_STRING",   /* 5 */
0091 "EXF_CARRAY",   /* 6 */
0092 "EXF_NONE",     /* 7 */
0093 "EXF_INT",      /* 8 */
0094 "EXF_ULONG",    /* 9 */
0095 "EXF_UINT",     /* 10 */
0096 "EXF_NTIMER",   /* 11 */
0097 "EXF_TIMET",    /* 12 */
0098 "EXF_USHORT",   /* 13 */
0099 "EXF_CARRAYFIX" /* 14 */
0100 };
0101 
0102 /* table_id filed, so that from each row we can identify table descriptor
0103  * we need a NR of elements in table so that we can perform binary search for descriptor.
0104  */
0105 
0106 #define TNC      0  /* net call */
0107 /* Converter for cmd_br_net_call_t */
0108 static cproto_t M_cmd_br_net_call_x[] = 
0109 {
0110     {TNC, 0x1005, "br_magic",  OFSZ(cmd_br_net_call_t,br_magic),   EXF_LONG, XFLD, 10, 10, NULL},
0111     {TNC, 0x100F, "msg_type",  OFSZ(cmd_br_net_call_t,msg_type),   EXF_CHAR, XFLD, 1, 1},
0112     {TNC, 0x1019, "command_id",OFSZ(cmd_br_net_call_t,command_id), EXF_INT,  XFLD, 1, 5},
0113     /*{TNC, 0x1023, "len",       OFSZ(cmd_br_net_call_t,len),        EXF_LONG, XSBL, 1, 10}, *< Not used ???? */
0114     {TNC, 0x102D, "buf",       OFSZ(cmd_br_net_call_t,buf),        EXF_NONE, XSUBPTR, 0, PMSGMAX, 
0115                        NULL, EXOFFSET(cmd_br_net_call_t,len), EXFAIL, classify_netcall},
0116     {TNC, EXFAIL}
0117 };
0118 
0119 /* Converter for standard ndrxd header. */
0120 #define TSH     1 /* standard hearder */
0121 static cproto_t M_stdhdr_x[] = 
0122 {
0123     {TSH, 0x1037, "command_id",    OFSZ(command_call_t,command_id),     EXF_SHORT, XFLD, 1, 4},
0124     {TSH, 0x1041, "proto_ver",     OFSZ(command_call_t,proto_ver),      EXF_CARRAYFIX, XFLD, 4, 4},
0125     /* it should be 0 AFAIK... */
0126     {TSH, 0x104B, "proto_magic",   OFSZ(command_call_t,proto_magic),    EXF_INT,  XFLD, 1, 1},
0127     {TSH, EXFAIL}
0128 };
0129 
0130 /* Converter for command_call_t */
0131 #define TCC     2 /* Command call */
0132 static cproto_t M_command_call_x[] = 
0133 {
0134     {TCC, 0x1055,  "stdhdr",       OFSZ0,                              EXF_NONE,   XINC, 1, PMSGMAX, M_stdhdr_x},
0135     {TCC, 0x105F,  "magic",        OFSZ(command_call_t,magic),         EXF_ULONG,  XFLD, 10, 10},
0136     {TCC, 0x1069,  "command",      OFSZ(command_call_t,command),       EXF_INT,    XFLD, 2, 2},
0137     {TCC, 0x1073,  "msg_type",     OFSZ(command_call_t,msg_type),      EXF_SHORT,  XFLD, 1, 2},
0138     {TCC, 0x107D,  "msg_src",      OFSZ(command_call_t,msg_src),       EXF_SHORT,  XFLD, 1, 1},
0139     {TCC, 0x1087,  "reply_queue",  OFSZ(command_call_t,reply_queue),   EXF_STRING, XFLD, 1, 128},
0140     {TCC, 0x1091,  "flags",        OFSZ(command_call_t,flags),         EXF_INT,    XFLD, 1, 5},
0141     {TCC, 0x109B,  "caller_nodeid",OFSZ(command_call_t,caller_nodeid), EXF_INT,    XFLD, 1, 3},
0142     {TCC, EXFAIL}
0143 };
0144 
0145 /* Convert for cmd_br_time_sync_t */
0146 #define TST     3   /* time sync table */
0147 static cproto_t M_cmd_br_time_sync_x[] = 
0148 {
0149     {TST, 0x10A5,  "call",       OFSZ0,                              EXF_NONE,   XINC, 1, PMSGMAX, M_command_call_x},
0150     {TST, 0x10AF,  "time",       OFSZ(cmd_br_time_sync_t,time),      EXF_NTIMER, XFLD, 40, 40},
0151     /* Support #623 */
0152     {TST, 0x10B0,  "mode",       OFSZ(cmd_br_time_sync_t,mode),             EXF_INT, XFLD, 1, 1},
0153     {TST, 0x10B1,  "seq",        OFSZ(cmd_br_time_sync_t,orig_seq),         EXF_LONG,XFLD, 1, 20},
0154     {TST, 0x10B2,  "orig_nodeid",OFSZ(cmd_br_time_sync_t,orig_nodeid),      EXF_INT, XFLD, 1, 3},
0155     {TST, 0x10B3,  "orig_timestamp", OFSZ(cmd_br_time_sync_t,orig_timestamp),EXF_LONG,XFLD, 1, 20},
0156     {TST, EXFAIL}
0157 };
0158 
0159 /* Convert for bridge_refresh_svc_t */
0160 #define TRS     4 /* Refresh services */     
0161 static cproto_t Mbridge_refresh_svc_x[] = 
0162 {
0163     {TRS, 0x10B9,  "mode",       OFSZ(bridge_refresh_svc_t,mode),    EXF_CHAR,    XFLD, 1, 1},
0164     {TRS, 0x10C3,  "svc_nm",     OFSZ(bridge_refresh_svc_t,svc_nm),  EXF_STRING,  XFLD, 1, MAXTIDENT},
0165     {TRS, 0x10CD,  "count",      OFSZ(bridge_refresh_svc_t,count),   EXF_INT,     XFLD, 1, 6},
0166     {TRS, EXFAIL}
0167 };
0168 
0169 /* Convert for bridge_refresh_t */
0170 #define TBR     5 /* bridege refresh */
0171 static cproto_t M_bridge_refresh_x[] = 
0172 {
0173     {TBR, 0x10D7,  "call",       OFSZ0,                              EXF_NONE,   XINC, 1, PMSGMAX, M_command_call_x},
0174     {TBR, 0x10E1,  "mode",       OFSZ(bridge_refresh_t,mode),        EXF_CHAR,   XFLD, 1, 1},
0175     {TBR, 0x10EB,  "count",      OFSZ(bridge_refresh_t,count),       EXF_INT,    XFLD, 1, 6},
0176     /* We will provide integer as counter for array:  */
0177     {TBR, 0x10F5,  "svcs",       OFSZ(bridge_refresh_t,svcs),        EXF_NONE,   XLOOP, 0, PMSGMAX, Mbridge_refresh_svc_x, 
0178                             EXOFFSET(bridge_refresh_t,count), sizeof(bridge_refresh_svc_t)},
0179     {TBR, EXFAIL}
0180 };
0181 
0182 /* TODO: Add T table for testing all data types and their ranges */
0183 
0184 /******************** STUFF FOR UBF *******************************************/
0185 expublic short ndrx_G_ubf_proto_tag_map[] = 
0186 {
0187     0x1113, /* BFLD_SHORT- 0   */
0188     0x111D, /* BFLD_LONG - 1     */
0189     0x1127, /* BFLD_CHAR - 2     */
0190     0x1131, /* BFLD_FLOAT - 3  */
0191     0x113B, /* BFLD_DOUBLE - 4 */
0192     0x1145, /* BFLD_STRING - 5 */
0193     0x114F, /* BFLD_CARRAY - 6 */
0194     
0195     0x1150, /* BFLD_INT - 7 */
0196     0x1151, /* BFLD_RFU0 - 8 */
0197     0x1152, /* BFLD_PTR - 9 */
0198     0x1153, /* BFLD_UBF - 10 */
0199     0x1154, /* BFLD_VIEW - 11 */
0200 };
0201 
0202 /**
0203  * View field type mapping table
0204  * typecode to tag
0205  */
0206 expublic short ndrx_G_view_proto_tag_map[] = 
0207 {
0208     0x1360, /* BFLD_SHORT- 0   */
0209     0x1361, /* BFLD_LONG - 1     */
0210     0x1362, /* BFLD_CHAR - 2     */
0211     0x1363, /* BFLD_FLOAT - 3  */
0212     0x1364, /* BFLD_DOUBLE - 4 */
0213     0x1365, /* BFLD_STRING - 5 */
0214     0x1366, /* BFLD_CARRAY - 6 */
0215     0x1367, /* BFLD_INT - 7 */
0216 };
0217 
0218 #define UBF_TAG_BFLDID     0x10FF
0219 #define UBF_TAG_BFLDLEN    0x1109
0220 
0221 /* Helper driver table for UBF buffer. */
0222 #define TUF         6 /* ubf field */
0223 static cproto_t M_ubf_field[] = 
0224 {
0225     {TUF, 0x10FF,  "bfldid", OFSZ(proto_ufb_fld_t, bfldid),  EXF_UINT,   XFLD, 1, 9},
0226     /*{TUF, 0x1109,  "bfldlen",OFSZ(proto_ufb_fld_t, bfldlen), EXF_INT,   XSBL, 1, 10},--not needed, as encoded in TLV */
0227     /* Typed fields... */
0228     {TUF, 0x1113,  "short", OFSZ(proto_ufb_fld_t, buf), EXF_SHORT,   XFLDPTR, 1, 6},
0229     {TUF, 0x111D,  "long",  OFSZ(proto_ufb_fld_t, buf), EXF_LONG,    XFLDPTR, 1, 20},
0230     {TUF, 0x1127,  "char",  OFSZ(proto_ufb_fld_t, buf), EXF_CHAR,    XFLDPTR, 1, 1},
0231     {TUF, 0x1131,  "float", OFSZ(proto_ufb_fld_t, buf), EXF_FLOAT,   XFLDPTR, 1, 40},
0232     {TUF, 0x113B,  "double",OFSZ(proto_ufb_fld_t, buf), EXF_DOUBLE,  XFLDPTR, 1, 40},
0233     {TUF, 0x1145,  "string",OFSZ(proto_ufb_fld_t, buf), EXF_STRING,  XFLDPTR, 0, PMSGMAX},
0234     {TUF, 0x114F,  "carray",OFSZ(proto_ufb_fld_t, buf), EXF_CARRAY,  XFLDPTR, 0, PMSGMAX,
0235                             /* Using counter offset as carry len field... */
0236                             NULL, EXOFFSET(proto_ufb_fld_t,bfldlen), EXFAIL, NULL},
0237     {TUF, 0x1152,  "ptr",  OFSZ(proto_ufb_fld_t, buf), EXF_LONG,    XFLDPTR, 1, 20},
0238                             
0239     {TUF, 0x1153,  "ubf",  OFSZ(proto_ufb_fld_t,buf),  EXF_NONE,  XATMIBUFPTR, 0, PMSGMAX, NULL, 
0240                 /* using uint len and full tag (from which at offset we extract the buffer type) */
0241             EXOFFSET(proto_ufb_fld_t,typelen), EXFAIL, NULL, EXOFFSET(proto_ufb_fld_t,bfldid)},
0242     
0243     {TUF, 0x1154,  "view",  OFSZ(proto_ufb_fld_t,buf),  EXF_NONE,  XATMIBUFPTR, 0, PMSGMAX, NULL, 
0244                 /* using uint len and full tag (from which at offset we extract the buffer type) */
0245             EXOFFSET(proto_ufb_fld_t,typelen), EXFAIL, NULL, EXOFFSET(proto_ufb_fld_t,bfldid)},
0246                             
0247     {TUF, EXFAIL}
0248 };
0249 
0250 /* Converter for  tp_command_call_t */
0251 #define TTC        7 /* tpcall */
0252 static cproto_t M_tp_command_call_x[] = 
0253 {
0254     {TTC, 0x1159,  "stdhdr",    OFSZ0,                            EXF_NONE,    XINC, 1, PMSGMAX, M_stdhdr_x},
0255     {TTC, 0x116D,  "name",      OFSZ(tp_command_call_t,name),     EXF_STRING, XFLD, 0, XATMI_SERVICE_NAME_LENGTH},
0256     {TTC, 0x1177,  "reply_to",  OFSZ(tp_command_call_t,reply_to), EXF_STRING, XFLD, 0, NDRX_MAX_Q_SIZE},
0257     {TTC, 0x1181,  "callstack", OFSZ(tp_command_call_t,callstack),EXF_STRING, XFLD, 0, CONF_NDRX_NODEID_COUNT},
0258     {TTC, 0x118B,  "my_id",     OFSZ(tp_command_call_t,my_id),    EXF_STRING, XFLD, 0, NDRX_MAX_ID_SIZE},
0259     {TTC, 0x1195,  "sysflags",  OFSZ(tp_command_call_t,sysflags), EXF_LONG,   XFLD, 1, 20},
0260     {TTC, 0x119F,  "cd",        OFSZ(tp_command_call_t,cd),       EXF_INT,    XFLD, 1, 5},
0261     {TTC, 0x11A9,  "rval/usr1", OFSZ(tp_command_call_t,rval),     EXF_INT,    XFLD, 1, 10},
0262     {TTC, 0x11B3,  "rcode/usr2",OFSZ(tp_command_call_t,rcode),    EXF_LONG,   XFLD, 1, 20},
0263     {TTC, 0x11B4,  "user3",     OFSZ(tp_command_call_t,user3),    EXF_INT,    XFLD, 1, 10},
0264     {TTC, 0x11B5,  "user4",     OFSZ(tp_command_call_t,user4),    EXF_LONG,   XFLD, 1, 20},
0265     {TTC, 0x11B6,  "clttout",   OFSZ(tp_command_call_t,clttout),  EXF_INT,   XFLD, 1, 10},
0266     {TTC, 0x11BD,  "extradata", OFSZ(tp_command_call_t,extradata),EXF_STRING, XFLD, 0, 41},
0267     {TTC, 0x11C7,  "flags",     OFSZ(tp_command_call_t,flags),    EXF_LONG,   XFLD, 1, 20},
0268     {TTC, 0x11D1,  "timestamp", OFSZ(tp_command_call_t,timestamp),EXF_LONG,   XFLD, 1, 20},
0269     {TTC, 0x11DB,  "callseq",   OFSZ(tp_command_call_t,callseq),  EXF_UINT,   XFLD, 1, 10},
0270     {TTC, 0x11DC,  "msgseq",    OFSZ(tp_command_call_t,msgseq),   EXF_UINT,   XFLD, 1, 10},
0271     {TTC, 0x11E5,  "timer",     OFSZ(tp_command_call_t,timer),    EXF_NTIMER, XFLD, 40, 40},
0272     /* {TTC, 0x11EF,  "data_len",  OFSZ(tp_command_call_t,data_len), EXF_LONG,   XSBL, 1, 10}, - machine dependent (not need to send) */
0273     {TTC, 0x11F9,  "data",      OFSZ(tp_command_call_t,data),     EXF_NONE,  XMASTERBUF, 0, PMSGMAX, NULL, 
0274                             /* WARNING! Using counter offset here are length FLD offset! */
0275                            EXOFFSET(tp_command_call_t,data_len), EXFAIL, NULL, EXFAIL},
0276     {TTC, 0x1203,  "tmxid",  OFSZ(tp_command_call_t,tmxid),    EXF_STRING, XFLD, 0, NDRX_XID_SERIAL_BUFSIZE},
0277     {TTC, 0x120D,  "tmrmid", OFSZ(tp_command_call_t, tmrmid), EXF_SHORT,   XFLD,    1, 5},
0278     {TTC, 0x1217,  "tmnodeid", OFSZ(tp_command_call_t, tmnodeid), EXF_SHORT,XFLD,   1, 5},
0279     {TTC, 0x1221,  "tmsrvid", OFSZ(tp_command_call_t, tmsrvid), EXF_SHORT,  XFLD,   1, 5},
0280     {TTC, 0x122B,  "tmknownrms",OFSZ(tp_command_call_t,tmknownrms),    EXF_STRING, XFLD, 0, NDRX_MAX_RMS},
0281     /* Is transaction marked as abort only? */
0282     {TTC, 0x1235,  "tmtxflags", OFSZ(tp_command_call_t, tmtxflags), EXF_SHORT, XFLD, 1, 5},
0283     {TTC, EXFAIL}
0284 };
0285 
0286 /* Converter for  tp_notif_call_t */
0287 #define TPN        8 /* tpnotify/tpbroadcast */
0288 static cproto_t M_tp_notif_call_x[] = 
0289 {
0290     {TPN, 0x123F,  "stdhdr",    OFSZ0,                            EXF_NONE,    XINC, 1, PMSGMAX, M_stdhdr_x},
0291     {TPN, 0x1249,  "destclient",OFSZ(tp_notif_call_t,destclient),EXF_STRING,   XFLD, 0, NDRX_MAX_ID_SIZE},
0292     
0293     {TPN, 0x1253,  "nodeid",      OFSZ(tp_notif_call_t,nodeid),     EXF_STRING, XFLD, 0, MAXTIDENT*2},
0294     {TPN, 0x125D,  "nodeid_isnull",  OFSZ(tp_notif_call_t,nodeid_isnull), EXF_INT, XFLD, 1, 1},
0295     
0296     {TPN, 0x1267,  "usrname",      OFSZ(tp_notif_call_t,usrname),     EXF_STRING, XFLD, 0, MAXTIDENT*2},
0297     {TPN, 0x1271,  "usrname_isnull",  OFSZ(tp_notif_call_t,usrname_isnull), EXF_INT, XFLD, 1, 1},
0298     
0299     {TPN, 0x127B,  "cltname",      OFSZ(tp_notif_call_t,cltname),     EXF_STRING, XFLD, 0, MAXTIDENT*2},
0300     {TPN, 0x1285,  "cltname_isnull",  OFSZ(tp_notif_call_t,cltname_isnull), EXF_INT, XFLD, 1, 1},
0301     
0302     {TPN, 0x1299,  "reply_to",  OFSZ(tp_notif_call_t,reply_to), EXF_STRING, XFLD, 0, NDRX_MAX_Q_SIZE},
0303     
0304     {TPN, 0x12A3,  "callstack", OFSZ(tp_notif_call_t,callstack),EXF_STRING, XFLD, 0, CONF_NDRX_NODEID_COUNT},
0305     {TPN, 0x12AD,  "my_id",     OFSZ(tp_notif_call_t,my_id),    EXF_STRING, XFLD, 0, NDRX_MAX_ID_SIZE},
0306     {TPN, 0x12B7,  "sysflags",  OFSZ(tp_notif_call_t,sysflags), EXF_LONG,   XFLD, 1, 20},
0307     {TPN, 0x12C1,  "cd",        OFSZ(tp_notif_call_t,cd),       EXF_INT,    XFLD, 1, 5},
0308     {TPN, 0x12CB,  "rval",      OFSZ(tp_notif_call_t,rval),     EXF_INT,    XFLD, 1, 10},
0309     {TPN, 0x12D5,  "rcode",     OFSZ(tp_notif_call_t,rcode),    EXF_LONG,   XFLD, 1, 20},
0310     {TPN, 0x12DF,  "flags",     OFSZ(tp_notif_call_t,flags),    EXF_LONG,   XFLD, 1, 20},
0311     {TPN, 0x12E9,  "timestamp", OFSZ(tp_notif_call_t,timestamp),EXF_LONG,   XFLD, 1, 20},
0312     {TPN, 0x12F3,  "callseq",   OFSZ(tp_notif_call_t,callseq),  EXF_UINT,   XFLD, 1, 10},
0313     {TPN, 0x12FD,  "msgseq",    OFSZ(tp_notif_call_t,msgseq),   EXF_UINT,   XFLD, 1, 10},
0314     {TPN, 0x1307,  "timer",     OFSZ(tp_notif_call_t,timer),    EXF_NTIMER, XFLD, 40, 40},
0315     /* {TPN, 0x1311,  "data_len",  OFSZ(tp_notif_call_t,data_len), EXF_LONG,   XSBL, 1, 10}, -machine dependent, no need to send */
0316     {TPN, 0x131B,  "data",      OFSZ(tp_notif_call_t,data),     EXF_NONE,  XMASTERBUF, 0, PMSGMAX, NULL, 
0317                 /* WARNING! Using counter offset here are length FLD offset! */
0318                EXOFFSET(tp_notif_call_t,data_len), EXFAIL, NULL, EXFAIL},
0319     {TPN, 0x1325,  "destnodeid",OFSZ(tp_notif_call_t,destnodeid),    EXF_LONG,   XFLD, 1, 20},
0320     {TPN, EXFAIL}
0321 };
0322 
0323 /**
0324  * This drives master buffer
0325  */
0326 #define MBU        9 /* multi-buffer */
0327 expublic cproto_t ndrx_G_ndrx_mbuf_tlv_x[] = 
0328 {
0329     {MBU, 0x132F,  "tag",   OFSZ(ndrx_mbuf_tlv_t, tag),  EXF_UINT,   XFLD, 1, 10},
0330     /* {MBU, 0x1339,  "len",   OFSZ(ndrx_mbuf_tlv_t, len), EXF_UINT,   XFLD, 1, 10}, - platform dependent... */
0331     /* Typed fields... */
0332     {MBU, 0x1343,  "data",  OFSZ(ndrx_mbuf_tlv_t,data),     EXF_NONE,  XATMIBUF|XFLAST, 0, PMSGMAX, NULL, 
0333                 /* using uint len and full tag (from which at offset we extract the buffer type) */
0334             EXOFFSET(ndrx_mbuf_tlv_t,len), EXFAIL, NULL, EXOFFSET(ndrx_mbuf_tlv_t,tag)},
0335     {MBU, EXFAIL}
0336 };
0337 
0338 /* Helper driver table for VIEW buffer. 
0339  * Last 4 bits of the tag matches the BFLD_X type.
0340  */
0341 #define TVF         10 /* view field */
0342 expublic cproto_t ndrx_G_view_field[] = 
0343 {
0344     {TVF, 0x134D,  "cname", OFSZ(proto_ufb_fld_t, cname),  EXF_STRING,   XFLD, 1, NDRX_VIEW_CNAME_LEN},
0345     /* For UBF we could optimize this out? Do not send it at times? */
0346     /* {TVF, 0x1357,  "bfldlen",OFSZ(proto_ufb_fld_t, bfldlen), EXF_INT,   XSBL, 1, 10}, this is encoded in tag len*/
0347     /* Typed fields... */
0348     {TVF, 0x1360,  "short", OFSZ(proto_ufb_fld_t, buf), EXF_SHORT,   XFLDPTR, 1, 6},
0349     {TVF, 0x1361,  "long",  OFSZ(proto_ufb_fld_t, buf), EXF_LONG,    XFLDPTR, 1, 20},
0350     {TVF, 0x1362,  "char",  OFSZ(proto_ufb_fld_t, buf), EXF_CHAR,    XFLDPTR, 1, 1},
0351     {TVF, 0x1363,  "float", OFSZ(proto_ufb_fld_t, buf), EXF_FLOAT,   XFLDPTR, 1, 40},
0352     {TVF, 0x1364,  "double",OFSZ(proto_ufb_fld_t, buf), EXF_DOUBLE,  XFLDPTR, 1, 40},
0353     {TVF, 0x1365,  "string",OFSZ(proto_ufb_fld_t, buf), EXF_STRING,  XFLDPTR, 0, PMSGMAX},
0354     {TVF, 0x1366,  "carray",OFSZ(proto_ufb_fld_t, buf), EXF_CARRAY,  XFLDPTR, 0, PMSGMAX,
0355                             /* Using counter offset as carry len field... */
0356                             NULL, EXOFFSET(proto_ufb_fld_t,bfldlen), EXFAIL, NULL},
0357     /* int padded with sign in front */
0358     {TVF, 0x1367,  "int",   OFSZ(proto_ufb_fld_t, buf), EXF_INT,     XFLDPTR, 1, 12},
0359     {TVF, EXFAIL}
0360 };
0361 
0362 /**
0363  * View header data
0364  */
0365 #define TVH         11 /* view */
0366 expublic cproto_t ndrx_G_view[] = 
0367 {
0368     {TVH, 0x13B1, "vname", OFSZ(BVIEWFLD, vname),       EXF_STRING,   XFLD,            0, NDRX_VIEW_NAME_LEN},
0369     {TVH, 0x13BB, "vflags", OFSZ(BVIEWFLD, vflags),     EXF_UINT  ,   XFLD|XFLAST, 1, 1},
0370     {TVH, EXFAIL}
0371 };
0372 
0373 /**
0374  * Get the number of elements in array.
0375  */
0376 static ptinfo_t M_ptinfo[] = 
0377 {
0378     {TNC, N_DIM(M_cmd_br_net_call_x)},
0379     {TSH, N_DIM(M_stdhdr_x)},
0380     {TCC, N_DIM(M_command_call_x)},
0381     {TST, N_DIM(M_cmd_br_time_sync_x)},
0382     {TRS, N_DIM(Mbridge_refresh_svc_x)},
0383     {TBR, N_DIM(M_bridge_refresh_x)},
0384     {TUF, N_DIM(M_ubf_field)},
0385     {TTC, N_DIM(M_tp_command_call_x)},
0386     {TPN, N_DIM(M_tp_notif_call_x)},
0387     {MBU, N_DIM(ndrx_G_ndrx_mbuf_tlv_x)},
0388     {TVF, N_DIM(ndrx_G_view_field)},
0389     {TVH, N_DIM(ndrx_G_view)},
0390 };
0391 
0392 /* Message conversion tables */
0393 
0394 /* NDRXD messages: */
0395 static xmsg_t M_ndrxd_x[] = 
0396 {
0397     {'A', 0, /*any*/             "atmi_any",    XTAB2(M_cmd_br_net_call_x, M_tp_command_call_x)},
0398     {'N', ATMI_COMMAND_TPNOTIFY, "notif",       XTAB2(M_cmd_br_net_call_x, M_tp_notif_call_x)},
0399     {'N', ATMI_COMMAND_BROADCAST, "broadcast",  XTAB2(M_cmd_br_net_call_x, M_tp_notif_call_x)},
0400     {'X', NDRXD_COM_BRCLOCK_RQ,  "brclockreq",  XTAB2(M_cmd_br_net_call_x, M_cmd_br_time_sync_x)},
0401     {'X', NDRXD_COM_BRREFERSH_RQ,"brrefreshreq",XTAB2(M_cmd_br_net_call_x, M_bridge_refresh_x)},
0402     {EXFAIL, EXFAIL}
0403 };
0404 
0405 /*---------------------------Statics------------------------------------*/
0406 /*---------------------------Prototypes---------------------------------*/
0407 
0408 exprivate inline int exproto_cklen(cproto_t *fld, int net_len, char *data_start);
0409 
0410 #define FIX_SIGND(x) if ('1'==bdc_sign) *x = -1 * (*x);
0411 #define FIX_SIGNF(x) if ('1'==bdc_sign) *x = -1.0 * (*x);
0412 
0413 /**
0414  * BCD Encoding rules:
0415  * 
0416  * signed decimals:
0417  * Prefix 0 if needs to align to bytes.
0418  * Always: Postfix 0 - if sign >=0.
0419  *         Postfix 1 - if sign < 0.
0420  * For example:
0421  * Number: 012331 = -1233
0422  * 
0423  * Floats encodes with 5 digits (doubles with 6 implied dec pos) after comma:
0424  * For example -14.55 will be encoded as:
0425  *          14550001
0426  * For example 14.55 will be ecoded as:
0427  *          14550000
0428  * 
0429  * 
0430  * @param fld
0431  * @param c_buf_in - input data
0432  * @param proto_buf - output protocol buffer
0433  * @param proto_bufsz - total buffer size
0434  * @param proto_buf_offset - current offset in protocol buffer
0435  * @param c_buf_in_len - data len, only for carray.
0436  * @return 
0437  */
0438 exprivate inline int x_ctonet(cproto_t *fld, char *c_buf_in,  
0439                         char *proto_buf, int proto_bufsz, long *proto_buf_offset,
0440                         char *debug_buf, int debug_bufsz, int c_buf_in_len)
0441 {
0442     int ret=EXSUCCEED;
0443     int i;
0444     int conv_bcd = EXFALSE;
0445     char numbuf[1024];
0446     int len=0; /* increment len */
0447     /* Bug #182 added ABS fix. */
0448     switch (fld->fld_type)
0449     {
0450         case EXF_SHORT:
0451         {
0452             short *tmp = (short *)c_buf_in;
0453             short tmp_abs = (short)abs(*tmp);
0454             MKSIGN;
0455             snprintf(numbuf, sizeof(numbuf), "%hd%c", tmp_abs, sign);
0456             conv_bcd = EXTRUE;
0457         }
0458             break;
0459         case EXF_LONG:
0460         {
0461             long *tmp = (long *)c_buf_in;
0462             MKSIGN;
0463             snprintf(numbuf, sizeof(numbuf), "%ld%c", labs(*tmp), sign);
0464             conv_bcd = EXTRUE;
0465         }
0466             break;
0467         case EXF_CHAR:
0468         {
0469             char *tmp = (char *)c_buf_in;
0470             CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, 2);
0471             
0472             proto_buf[*proto_buf_offset] = *tmp;
0473             proto_buf[*proto_buf_offset+1] = 0; /* later for strcpy */
0474 
0475             /* -> what if 0x00 byte? Isn't it more correct just to use len 1?
0476             len = strlen(&(proto_buf[*proto_buf_offset]));
0477             */
0478             len = 1;
0479 
0480             *proto_buf_offset += len;
0481             
0482         }
0483             break;
0484         case EXF_FLOAT:
0485         {
0486             float *tmp = (float *)c_buf_in;
0487             float tmp_op = *tmp;
0488             float tmp_abs;
0489             MKSIGN;
0490             
0491             for (i=0; i<FLOAT_RESOLUTION; i++)
0492                 tmp_op*=10.0f;
0493             
0494             tmp_abs = (float)fabs(tmp_op);
0495                     
0496             snprintf(numbuf, sizeof(numbuf), "%.0lf%c", tmp_abs, sign);
0497             
0498             conv_bcd = EXTRUE;
0499         }
0500             break;
0501         case EXF_DOUBLE:
0502         {
0503             double *tmp = (double *)c_buf_in;
0504             double tmp_op = *tmp;
0505             MKSIGN;
0506             
0507             for (i=0; i<DOUBLE_RESOLUTION; i++)
0508                 tmp_op*=10.0f;
0509             
0510             snprintf(numbuf, sizeof(numbuf), "%.0lf%c", fabs(tmp_op), sign);
0511             
0512             conv_bcd = EXTRUE;
0513             
0514         }
0515             break;
0516         case EXF_STRING:
0517         {
0518             /* EOS must be present in c struct! */
0519             len = strlen(c_buf_in);
0520             
0521             CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, len+1);
0522             
0523             NDRX_STRCPY_SAFE_DST((proto_buf+(*proto_buf_offset)), c_buf_in, 
0524                     (proto_bufsz - (*proto_buf_offset)) );
0525             
0526             *proto_buf_offset += len;
0527             
0528             /* need some debug too... */
0529             
0530             if (debug_get_ndrx_level() >= log_debug)
0531             {
0532                 NDRX_STRCPY_SAFE_DST(debug_buf, c_buf_in, debug_bufsz);
0533             }
0534         }
0535             break;
0536         case EXF_INT:
0537         {
0538             int *tmp = (int *)c_buf_in;
0539             MKSIGN;
0540             snprintf(numbuf, sizeof(numbuf), "%d%c", abs(*tmp), sign);
0541             conv_bcd = EXTRUE;
0542         }
0543             break;
0544         case EXF_ULONG:
0545         {
0546             unsigned long *tmp = (unsigned long *)c_buf_in;
0547             snprintf(numbuf, sizeof(numbuf), "%lu", *tmp);
0548             conv_bcd = EXTRUE;
0549         }
0550             break;
0551         case EXF_UINT:
0552         {
0553             unsigned *tmp = (unsigned *)c_buf_in;
0554             snprintf(numbuf, sizeof(numbuf), "%u", *tmp);
0555             conv_bcd = EXTRUE;
0556         }   
0557             break;
0558         case EXF_USHORT:
0559         {
0560             unsigned short *tmp = (unsigned short *)c_buf_in;
0561             snprintf(numbuf, sizeof(numbuf), "%hu", *tmp);
0562             conv_bcd = EXTRUE;
0563         }    
0564             break;
0565         case EXF_NTIMER:
0566         {
0567             ndrx_stopwatch_t *tmp = (ndrx_stopwatch_t *)c_buf_in;
0568             snprintf(numbuf, sizeof(numbuf), "%020ld%020ld", tmp->t.tv_sec, 
0569                     tmp->t.tv_nsec);
0570             NDRX_LOG(6, "time=>[%s]", numbuf);
0571             
0572             NDRX_LOG(log_debug, "timer = (tv_sec: %ld tv_nsec: %ld)"
0573                                     " delta: %d", 
0574                                     tmp->t.tv_sec,  tmp->t.tv_nsec, 
0575                                     ndrx_stopwatch_get_delta_sec(tmp));
0576             
0577             conv_bcd = EXTRUE;
0578         }    
0579             break;
0580         case EXF_CARRAY:
0581         {
0582             /* Support for carray field. */
0583             
0584             CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, c_buf_in_len);
0585             
0586             memcpy(proto_buf+*proto_buf_offset, c_buf_in, c_buf_in_len);
0587             *proto_buf_offset += c_buf_in_len;
0588             len = c_buf_in_len;
0589             
0590             /* Built representation for user... for debug purposes... */
0591             if (debug_get_ndrx_level() >= log_debug)
0592             {
0593                 ndrx_build_printable_string(debug_buf, debug_bufsz, 
0594                         proto_buf+*proto_buf_offset-c_buf_in_len, c_buf_in_len);
0595             }
0596         }    
0597             break;
0598                 
0599         case EXF_CARRAYFIX:
0600             
0601             /* fixed len carray */
0602             
0603             CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, fld->min_len);
0604             
0605             memcpy(proto_buf+*proto_buf_offset, c_buf_in, fld->min_len);
0606             *proto_buf_offset += fld->min_len;
0607             len = fld->min_len;
0608             
0609             /* Built representation for user... for debug purposes... */
0610             if (debug_get_ndrx_level() >= log_debug)
0611             {
0612                 ndrx_build_printable_string(debug_buf, debug_bufsz, 
0613                         proto_buf+*proto_buf_offset-fld->min_len, fld->min_len);
0614             }
0615             
0616             break;
0617             
0618         case EXF_NONE:
0619         default:
0620             NDRX_LOG(log_error, "I do not know how to convert %d "
0621                     "type to network!", fld->fld_type);
0622             ret=EXFAIL;
0623             goto out;
0624             break;
0625     }
0626     
0627     if (debug_get_ndrx_level() >= log_debug)
0628     {
0629         if (conv_bcd)
0630         {
0631             NDRX_STRCPY_SAFE_DST(debug_buf, numbuf, debug_bufsz);
0632         } /* for carrays debug infos is already built */
0633         else if (EXF_CARRAY!=fld->fld_type && EXF_CARRAYFIX!=fld->fld_type)
0634         {
0635             NDRX_STRCPY_SAFE_DST(debug_buf, proto_buf + (*proto_buf_offset)-len, debug_bufsz);
0636         }
0637     }
0638     /* else should be set up already by carray func! */
0639     
0640     /* Perform length check here... */
0641     if (conv_bcd)
0642     {
0643         char bcd_tmp[1024];
0644         char tmp_char_buf[3];
0645         int hex_dec;
0646         int j;
0647         int bcd_tmp_len;
0648         int bcd_pos = 0;
0649         
0650         if (strlen(numbuf) % 2)
0651         {
0652             NDRX_STRCPY_SAFE(bcd_tmp, "0");
0653             strcat(bcd_tmp, numbuf);
0654         }
0655         else
0656         {
0657             NDRX_STRCPY_SAFE(bcd_tmp, numbuf);
0658         }
0659         
0660         /* Now process char by char */
0661         bcd_tmp_len = strlen(bcd_tmp);
0662         
0663         CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, (bcd_tmp_len / 2));
0664         
0665         for (j=0; j<bcd_tmp_len; j+=2)
0666         {
0667             NDRX_STRCPY_SAFE(tmp_char_buf, bcd_tmp+j);
0668             sscanf(tmp_char_buf, "%x", &hex_dec);
0669             
0670             /*NDRX_LOG(log_error, "got hex 0x%x (org: %s)", hex_dec, numbuf);*/
0671             
0672             proto_buf[(*proto_buf_offset) + bcd_pos] = (char)(hex_dec & 0xff);
0673             /*NDRX_LOG(6, "put[%d] %x",bcd_pos, c_buf_out[bcd_pos]);*/
0674                     
0675             bcd_pos++;
0676         }
0677         *proto_buf_offset += (bcd_tmp_len / 2);
0678     }
0679     
0680 out:
0681     return ret;
0682 }
0683 
0684 /**
0685  * Convert net primitive field to c
0686  * @param fld - field descriptor
0687  * @param net_buf - net buffer
0688  * @param net_buf_offset - data offset in netbuffer
0689  * @param tag_len - length mentioned in tag
0690  * @param c_buf_out - c structure where data should be written
0691  * @return SUCCEED/FAIL
0692  */
0693 exprivate inline int x_nettoc(cproto_t *fld, 
0694                     char *net_buf, long net_buf_offset, int tag_len, /* in */
0695                     char *c_buf_out, BFLDLEN *p_bfldlen, char *debug_buf, 
0696                     int debug_len, long c_bufsz) /* out */
0697 {
0698     int ret=EXSUCCEED;
0699     int i, j;
0700     int conv_bcd = EXFALSE;
0701     int bcd_sign_used = EXFALSE;
0702     char bcd_buf[1024] = {EXEOS};
0703     char tmp[1024];
0704     char bdc_sign;
0705     char *datap = (net_buf + net_buf_offset);
0706     
0707     NDRX_LOG(log_debug, "%s: ex_buf/c_buf_out: %p", __func__, c_buf_out);
0708     
0709     debug_buf[0] = EXEOS;
0710     
0711     /* We should detect is this bcd field or not? */
0712     switch (fld->fld_type)
0713     {
0714         case EXF_SHORT:
0715         case EXF_LONG:
0716         case EXF_FLOAT:
0717         case EXF_DOUBLE:
0718         case EXF_INT:
0719         {
0720             conv_bcd = EXTRUE;
0721             bcd_sign_used = EXTRUE;
0722         }
0723         case EXF_ULONG:
0724         case EXF_UINT:
0725         case EXF_USHORT:
0726         case EXF_NTIMER:
0727             conv_bcd = EXTRUE;
0728             break;
0729     }
0730     
0731     /* Convert BCD to string. */
0732     if (conv_bcd)
0733     {
0734         int len;
0735         /*
0736         NDRX_LOG(log_debug, "Processing BCD... %p [%ld]", net_buf, net_buf_offset);
0737          */
0738         /* Convert all stuff to string  11 => */
0739         for (i=0; i< tag_len; i++)
0740         {
0741             /* so if we have 25, then it is 0x25 =>  */
0742             int net_byte;
0743             
0744             net_byte = net_buf[net_buf_offset + i] & 0xff; 
0745             
0746             snprintf(tmp, sizeof(tmp), "%02x", net_byte);
0747             strcat(bcd_buf, tmp);
0748         }
0749         
0750         /*
0751         NDRX_LOG(log_debug, "Got BDC: [%s]", bcd_buf);
0752         */
0753         /* Unsigned fields goes with out sign...! */
0754         if (bcd_sign_used)
0755         {
0756             len = strlen(bcd_buf);
0757             bdc_sign = bcd_buf[len-1];
0758             bcd_buf[len-1] = EXEOS;
0759 
0760             /*
0761             NDRX_LOG(log_debug, "Got BDC/sign: [%s]/[%c]", 
0762                     bcd_buf, bdc_sign);
0763              */
0764         }
0765     }
0766     
0767     
0768     switch (fld->fld_type)
0769     {
0770         case EXF_SHORT:
0771         {
0772             short *tmp = (short *)c_buf_out;
0773             
0774             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(short));
0775                     
0776             sscanf(bcd_buf, "%hd", tmp);
0777             FIX_SIGND(tmp);
0778             
0779             if (debug_get_ndrx_level() >= log_debug)
0780             {
0781                 snprintf(debug_buf, debug_len, "%hd", *tmp);
0782             }
0783         }
0784             break;
0785         case EXF_LONG:
0786         {
0787             long *tmp = (long *)c_buf_out;
0788             
0789             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(long));
0790             
0791             sscanf(bcd_buf, "%ld", tmp);
0792             
0793             FIX_SIGND(tmp);
0794           
0795             if (debug_get_ndrx_level() >= log_debug)
0796             {
0797                 snprintf(debug_buf, debug_len, "%ld", *tmp);
0798             }
0799         }
0800             break;
0801         case EXF_CHAR:
0802         {
0803             char *tmp = (char *)c_buf_out;
0804             
0805             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(char));
0806             
0807             tmp[0] = datap[0];
0808             
0809             if (debug_get_ndrx_level() >= log_debug)
0810             {
0811                 debug_buf[0] = tmp[0];
0812                 debug_buf[1] = EXEOS;
0813             }
0814         }
0815             break;
0816         case EXF_FLOAT:
0817         {
0818             float *tmp = (float *)c_buf_out;
0819             
0820             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(float));
0821             
0822             sscanf(bcd_buf, "%f", tmp);
0823             
0824             for (i=0; i<FLOAT_RESOLUTION; i++)
0825             {
0826                 *tmp= *tmp / 10.0;
0827             }
0828             
0829             FIX_SIGNF(tmp);
0830             
0831             if (debug_get_ndrx_level() >= log_debug)
0832             {
0833                 snprintf(debug_buf, debug_len, "%f", *tmp);
0834             }
0835             
0836         }
0837             break;
0838         case EXF_DOUBLE:
0839         {
0840             double *tmp = (double *)c_buf_out;
0841             
0842             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(double));
0843             
0844             sscanf(bcd_buf, "%lf", tmp);
0845             
0846             for (i=0; i<DOUBLE_RESOLUTION; i++)
0847             {
0848                 *tmp= *tmp / 10.0;
0849             }
0850             
0851             FIX_SIGNF(tmp);
0852             
0853             if (debug_get_ndrx_level() >= log_debug)
0854             {
0855                 snprintf(debug_buf, debug_len, "%lf", *tmp);
0856             }
0857         }
0858             break;
0859         case EXF_STRING:
0860         {
0861             /* EOS must be present in c struct! */
0862             /* include EOS in dest space calc.. */
0863             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, tag_len+1);
0864             
0865             NDRX_STRNCPY(c_buf_out, datap, tag_len);
0866             c_buf_out[tag_len] = EXEOS;
0867             
0868             /*NDRX_LOG(6, "%s = [%s] (string)", fld->cname, c_buf_out);*/
0869             
0870             if (debug_get_ndrx_level() >= log_debug)
0871             {
0872                 NDRX_STRCPY_SAFE_DST(debug_buf, c_buf_out, debug_len);
0873             }
0874         }
0875             break;
0876         case EXF_INT:
0877         {
0878             int *tmp = (int *)c_buf_out;
0879             
0880             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(int));
0881             
0882             sscanf(bcd_buf, "%d", tmp);
0883             
0884             FIX_SIGND(tmp);
0885             
0886             if (debug_get_ndrx_level() >= log_debug)
0887             {
0888                 snprintf(debug_buf, debug_len, "%d", *tmp);
0889             }
0890         }
0891             break;
0892         case EXF_ULONG:
0893         {
0894             unsigned long *tmp = (unsigned long *)c_buf_out;
0895             
0896             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(unsigned long));
0897             
0898             sscanf(bcd_buf, "%lu", tmp);
0899             
0900             if (debug_get_ndrx_level() >= log_debug)
0901             {
0902                 snprintf(debug_buf, debug_len, "%lu", *tmp);
0903             }
0904         }
0905             break;
0906         case EXF_UINT:
0907         {
0908             unsigned *tmp = (unsigned *)c_buf_out;
0909             
0910             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(unsigned));
0911             
0912             sscanf(bcd_buf, "%u", tmp);
0913             
0914             if (debug_get_ndrx_level() >= log_debug)
0915             {
0916                 snprintf(debug_buf, debug_len, "%u", *tmp);
0917             }
0918         }    
0919             break;
0920         case EXF_USHORT:
0921         {
0922             unsigned short *tmp = (unsigned short *)c_buf_out;
0923             
0924             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(unsigned short));
0925             
0926             sscanf(bcd_buf, "%hu", tmp);
0927             
0928             if (debug_get_ndrx_level() >= log_debug)
0929             {
0930                 snprintf(debug_buf, debug_len, "%hu", *tmp);
0931             }
0932         }    
0933             break;
0934         case EXF_NTIMER:
0935         {
0936             char timer_buf[21];
0937             char *p;
0938             ndrx_stopwatch_t *tmp = (ndrx_stopwatch_t *)c_buf_out;
0939             
0940             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, sizeof(ndrx_stopwatch_t));
0941             
0942             NDRX_STRCPY_SAFE(timer_buf, bcd_buf);
0943             
0944             p = timer_buf;
0945             while ('0'==*p) p++;
0946             
0947             NDRX_LOG(log_debug, "tv_sec=>[%s]", p);
0948             sscanf(p, "%ld", &(tmp->t.tv_sec));
0949             
0950             
0951             
0952             NDRX_STRCPY_SAFE(timer_buf, bcd_buf+20);
0953             p = timer_buf;
0954             while ('0'==*p) p++;
0955             
0956             NDRX_LOG(log_debug, "tv_nsec=>[%s]", p);
0957             sscanf(p, "%ld", &(tmp->t.tv_nsec));
0958             
0959             if (debug_get_ndrx_level() >= log_debug)
0960             {
0961                 snprintf(debug_buf, debug_len, "%s = [tv_sec = %ld "
0962                         "tv_nsec = %ld] (unsigned)", 
0963                         fld->cname, tmp->t.tv_sec, tmp->t.tv_nsec);
0964             }
0965         }    
0966             break;
0967         case EXF_CARRAY:
0968         case EXF_CARRAYFIX:
0969         {
0970             NDRX_LOG(log_debug, "carray tag len: %d (out buf: %p)", 
0971                     tag_len, c_buf_out);
0972             
0973             CHECK_EX_BUFSZ_SIMPLE(ret, c_bufsz, tag_len);
0974             
0975             memcpy(c_buf_out, datap, tag_len);
0976             *p_bfldlen = tag_len;
0977             
0978             if (debug_get_ndrx_level() >= log_debug)
0979             {
0980                 ndrx_build_printable_string(debug_buf, debug_len, c_buf_out, tag_len);
0981             }
0982             
0983         }    
0984             break;
0985         case EXF_NONE:
0986         default:
0987             NDRX_LOG(log_error, "I do not know how to convert %d "
0988                     "type to network!", fld->fld_type);
0989             ret=EXFAIL;
0990             goto out;
0991             break;
0992     }
0993     
0994 out:
0995     return ret;
0996 }
0997 
0998 /**
0999  * Read short (two bytes from network buffer).
1000  * usable for tag & len
1001  *s @param buf - network buffer
1002  * @param proto_buf_offset - offset where data starts
1003  * @return 
1004  */
1005 exprivate inline short read_net_short(char *buf, long *proto_buf_offset)
1006 {
1007     short net_val;
1008     short ret;
1009     
1010     memcpy((char *)&net_val, buf+*proto_buf_offset, 2);
1011     
1012     ret = ntohs(net_val);
1013     
1014     *proto_buf_offset+=2;
1015     
1016     return ret;
1017 }
1018 
1019 /**
1020  * Read 4 bytes from network 
1021  * @param buf - network buffer
1022  * @param proto_buf_offset - offset where data starts
1023  * @return 
1024  */
1025 exprivate inline int read_net_int(char *buf, long *proto_buf_offset)
1026 {
1027     int net_val;
1028     int ret;
1029     
1030     memcpy((char *)&net_val, buf+*proto_buf_offset, 4);
1031     
1032     ret = ntohl(net_val);
1033     
1034     *proto_buf_offset+=4;
1035     
1036     return ret;
1037 }
1038 
1039 /**
1040  * Put tag on network buffer.
1041  * @param tag - tag
1042  * @param buf - start of the buffer
1043  * @param proto_buf_offset - current offset of buffer
1044  */
1045 expublic inline int ndrx_write_tag(short tag, char *buf, long *proto_buf_offset, 
1046         long proto_bufsz)
1047 {
1048     int ret = EXSUCCEED;
1049     short net_tag;
1050     net_tag = htons(tag);
1051     
1052     /* Put tag on network */
1053     
1054     CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, TAG_BYTES);
1055     
1056     memcpy(buf+*proto_buf_offset, (char *)&net_tag, TAG_BYTES);
1057     *proto_buf_offset+=TAG_BYTES;
1058     
1059 out:
1060     return ret;
1061 }
1062 
1063 /**
1064  * Put len on network buffer.
1065  * @param len - len
1066  * @param buf - start of the buffer
1067  * @param proto_buf_offset - current offset of buffer
1068  */
1069 expublic inline int ndrx_write_len(int len, char *buf, long *proto_buf_offset, 
1070         long proto_bufsz)
1071 {
1072     int ret = EXSUCCEED;
1073     int net_len;
1074     net_len = htonl(len);
1075     /* Put tag on network */
1076     
1077     CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, LEN_BYTES);
1078     
1079     memcpy(buf+*proto_buf_offset, (char *)&net_len, LEN_BYTES);
1080     *proto_buf_offset+=LEN_BYTES;
1081     
1082 out:
1083     return ret;
1084 }
1085 
1086 /**
1087  * Validate the field data
1088  * @param fld field descr
1089  * @param net_len actual payload data len ( W/O tag/len)
1090  * @param data_start actual data to analyze  W/O tag/len
1091  * @return EXSUCCEED/EXFAIL (invalid data)
1092  */
1093 exprivate inline int exproto_cklen(cproto_t *fld, int net_len, char *data_start)
1094 {
1095     int abstract_len=0;
1096     char *p = data_start;
1097     int i;
1098     unsigned int tmp;
1099     int ret = EXSUCCEED;
1100     
1101     /* configure leading len */
1102     switch (fld->fld_type)
1103     {
1104         case EXF_SHORT:
1105         case EXF_LONG:
1106         case EXF_FLOAT:
1107         case EXF_DOUBLE:
1108         case EXF_INT:
1109         /* unsigned - do not count leading zero (as bcd requires spare one) */
1110         case EXF_ULONG:
1111         case EXF_UINT:
1112         case EXF_USHORT:
1113             
1114             /* strip off leading zeros */
1115             abstract_len = net_len*2;
1116             
1117             if (0==abstract_len)
1118             {
1119                 /* nothing to do if no data data received at all */
1120                 break;
1121             }
1122             
1123             p=data_start;
1124             for (i=0; i<net_len; i++)
1125             {
1126                 tmp = (unsigned char)*p;
1127                 
1128                 if ( (tmp >> 4) == 0 )
1129                 {
1130                     abstract_len--;
1131                 
1132                     if ( (tmp & 0xf) == 0 )
1133                     {
1134                         abstract_len--;
1135                     }
1136                     else
1137                     {
1138                         /* stop to strip */
1139                         break;
1140                     }
1141                 }
1142                 else
1143                 {
1144                     /* stop to strip */
1145                     break;
1146                 }
1147             }            
1148             
1149             if (EXF_SHORT==fld->fld_type ||
1150                 EXF_LONG==fld->fld_type ||
1151                 EXF_FLOAT==fld->fld_type ||
1152                 EXF_DOUBLE==fld->fld_type ||
1153                 EXF_INT==fld->fld_type)
1154             {
1155                 /* remove the sign... */
1156                 abstract_len--;
1157             }
1158             
1159             /* if value was zero +, then 00 is stipped to  abstract_len and then
1160              * -1. Thus as some value 0 was then we get then we abs len 1.
1161              */
1162             if (abstract_len<=0)
1163             {
1164                 abstract_len=1;
1165             }
1166             
1167             break;
1168         case EXF_NTIMER:
1169             
1170             /* just get the numbers - we know that it is even number
1171              * thus aligns over the 20 bytes / 40 bcd digits.
1172              */
1173             abstract_len = net_len*2;
1174             
1175             break;
1176         default:
1177             abstract_len = net_len;
1178     }
1179     
1180     /* test the output... */
1181     if ((abstract_len < fld->min_len)  || 
1182             (PMSGMAX == fld->max_len && abstract_len > NDRX_MSGSIZEMAX) ||
1183             (PMSGMAX != fld->max_len && abstract_len > fld->max_len))
1184     {
1185         NDRX_LOG(log_error, "WARNING! INVALID LEN! tag: 0x%x (%s) "
1186                 "min_len=%ld max_len=%ld but got: %d",
1187                 fld->tag, fld->cname, fld->min_len, fld->max_len, abstract_len);
1188         NDRX_DUMP(log_debug, "Invalid chunk:", 
1189                 data_start-(TAG_BYTES + LEN_BYTES), 
1190                 net_len + (TAG_BYTES + LEN_BYTES));
1191         EXFAIL_OUT(ret);
1192     }
1193     
1194 out:
1195             
1196     return ret;    
1197 }
1198 
1199 /**
1200  * Build network message by using xmsg record, this table is recursive...
1201  * TODO: Might we can avoid tmp -> directly write to ex_buf?!
1202  * @param cv
1203  * @param offset    Current offset in C structure
1204  * @param ex_buf - Enduro/X C buffer (machine specific structures)
1205  * @param ex_len - Enduro/X C side buffer len
1206  * @param proto_buf - output procol buffer
1207  * @param proto_len - actual number of bytes written to output buffer
1208  * @param proto_bufz - output buffer size max
1209  * @return EXSUCCEED/EXFAIL
1210  */
1211 expublic int exproto_build_ex2proto(xmsg_t *cv, int level, long offset,
1212         char *ex_buf, long ex_len, char *proto_buf, long *proto_buf_offset,
1213         short *accept_tags, proto_ufb_fld_t *p_ub_data, 
1214         long proto_bufsz)
1215 {
1216     int ret=EXSUCCEED;
1217     cproto_t *p = cv->tab[level];
1218     char debug[16*1024]; /* we might get prefix byte with \0X */
1219     /* Length memory: */
1220     int schedule_length = EXFALSE;
1221     cproto_t *len_rec;
1222     long len_offset;
1223     short *p_accept;
1224     int len_written; /* The length we used  */
1225     int max_len;
1226     
1227     NDRX_LOG(log_debug, "Building table: %s - enter at %p [%s] "
1228                         "tag: [0x%x], level: %d", 
1229                         cv->descr, ex_buf+offset, p->cname, p->tag, level);
1230     
1231     while (EXFAIL!=p->tag)
1232     {
1233         len_written = 0;
1234                 
1235         if (NULL!=accept_tags)
1236         {
1237             int accept = EXFALSE;
1238             /* Check acceptable tags... */
1239             p_accept = accept_tags;
1240             
1241             while (EXFAIL!=*p_accept)
1242             {
1243                 if (*p_accept == p->tag)
1244                 {
1245                     accept = EXTRUE;
1246                     break;
1247                 }
1248                 p_accept++;
1249             }
1250             
1251             if (!accept)
1252             {
1253                 goto tag_continue;
1254             }
1255         }
1256         /* Check the type and process accordingly... */
1257         switch (XTYPE(p->type))
1258         {
1259             case XFLDPTR:
1260             case XFLD:
1261             {
1262                 /* This is field... */
1263                 
1264                 long len_offset;
1265                 long off_start;
1266                 long off_stop;
1267                 char *dataptr;
1268                 
1269                 /* This is sub tlv/ thus put tag... */
1270                 if (EXSUCCEED!=ndrx_write_tag((short)p->tag, proto_buf, proto_buf_offset, 
1271                         proto_bufsz))
1272                 {
1273                     EXFAIL_OUT(ret);
1274                 }
1275                 
1276                 len_offset = *proto_buf_offset;
1277                 
1278                 CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, LEN_BYTES);
1279                 *proto_buf_offset=*proto_buf_offset+LEN_BYTES;
1280                 
1281                 off_start = *proto_buf_offset;
1282                 
1283                 
1284                 if (XFLDPTR==XTYPE(p->type))
1285                 {
1286                     /* pointer is stored in the buffer 
1287                      * For outgoings this is perfectly fine
1288                      * as data is somewhere in the RAM in acceptable
1289                      * format.
1290                      * No need to copy again to some temp buffers like for UBF
1291                      */
1292                     dataptr=*((char **)(ex_buf+offset+p->offset));
1293                 }
1294                 else
1295                 {
1296                     dataptr=ex_buf+offset+p->offset;
1297                 }
1298                 
1299                 if ( UBF_TAG_BFLD_CARRAY == p->tag ||
1300                         VIEW_TAG_CARRAY == p->tag)
1301                 {
1302                     ret = x_ctonet(p, dataptr, proto_buf, 
1303                             proto_bufsz, proto_buf_offset, debug, sizeof(debug), 
1304                             p_ub_data->bfldlen);
1305                 }
1306                 else
1307                 {
1308                     ret = x_ctonet(p, dataptr, proto_buf, proto_bufsz,
1309                             proto_buf_offset, debug, sizeof(debug), 0);
1310                 }
1311                 
1312                 if (EXSUCCEED!=ret)
1313                 {
1314                     NDRX_LOG(log_error, "Failed to convert tag %x: [%s] %ld "
1315                             "at offset %ld", p->tag, p->cname, p->offset);
1316                     ret=EXFAIL;
1317                     goto out;
1318                 }
1319                 
1320                 off_stop = *proto_buf_offset;
1321                 len_written = (int)(off_stop - off_start);
1322                 
1323                 NDRX_LOG(log_debug, "ex2net: tag: [0x%x]\t[%s]\t len:"
1324                         " %d (0x%04x) type:"
1325                         " [%s]\t data: [%s]"/*netbuf (tag start): %p"*/, 
1326                         p->tag, p->cname, len_written, len_written, 
1327                         M_type[p->fld_type], debug/*, 
1328                         (proto_buf+(*proto_buf_offset))*/ );
1329                 
1330                 /* Write data off */
1331                 
1332                 if (EXSUCCEED!=ndrx_write_len(len_written, proto_buf, &len_offset, 
1333                         proto_bufsz))
1334                 {
1335                     EXFAIL_OUT(ret);
1336                 }
1337                 
1338             }
1339                 break;
1340                 
1341             case XSUBPTR:
1342             case XSUB:
1343             {
1344                 /* <sub tlv> */
1345                 /* Reserve space for Tag/Length */
1346                 long len_offset;
1347                 long off_start;
1348                 long off_stop;
1349                 
1350                 NDRX_LOG(log_debug, "XSUB enter: tag: %x proto offset: %ld, c struct off: %ld", 
1351                         (int)p->tag, *proto_buf_offset, offset+p->offset);
1352                 /* This is sub tlv/ thus put tag... */
1353                 if (EXSUCCEED!=ndrx_write_tag((short)p->tag, proto_buf, proto_buf_offset, 
1354                         proto_bufsz))
1355                 {
1356                     EXFAIL_OUT(ret);
1357                 }
1358                 
1359                 len_offset = *proto_buf_offset;
1360                 
1361                 CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, LEN_BYTES);
1362                 *proto_buf_offset=*proto_buf_offset+LEN_BYTES;
1363                 
1364                 off_start = *proto_buf_offset;
1365                 /* </sub tlv> */
1366                 
1367                 /* This is sub field, we should run it from subtable... */
1368                 if (XSUBPTR==XTYPE(p->type))
1369                 {
1370                     char *ex_buf_ptr = *((char **)(ex_buf+offset+p->offset));
1371                     ret = exproto_build_ex2proto(cv, level+1, 0,
1372                             ex_buf_ptr, ex_len, proto_buf, proto_buf_offset, NULL, NULL,
1373                             proto_bufsz);
1374                 }
1375                 else
1376                 {
1377                     ret = exproto_build_ex2proto(cv, level+1, offset+p->offset,
1378                             ex_buf, ex_len, proto_buf, proto_buf_offset, NULL, NULL,
1379                             proto_bufsz);
1380                 }
1381                 
1382                 if (EXSUCCEED!=ret)
1383                 {
1384                     NDRX_LOG(log_error, "Failed to convert sub/tag %x: [%s] %ld"
1385                             "at offset %ld", p->tag, p->cname, p->offset);
1386                     EXFAIL_OUT(ret);
1387                 }
1388                 
1389                 /* <sub tlv> */
1390                 off_stop = *proto_buf_offset;
1391                 /* Put back len there.. */
1392                 len_written = (int)(off_stop - off_start);
1393                 /* this should be ok, but check anyway */
1394                 if (EXSUCCEED!=ndrx_write_len(len_written, proto_buf, &len_offset, 
1395                         proto_bufsz))
1396                 {
1397                     EXFAIL_OUT(ret);
1398                 }
1399                 /* </sub tlv> */
1400             }
1401                 break;
1402             case XSBL:
1403             {
1404                 schedule_length = EXTRUE;
1405                 /* We should save offset in output buffer for TLV */
1406                 len_offset = *proto_buf_offset;
1407                 len_rec = p;
1408                 NDRX_LOG(6, "XSBL at %p", ex_buf+offset+p->offset);
1409             }
1410                 break;
1411             case XINC:
1412             {
1413                 xmsg_t tmp_cv;
1414                 
1415                 /* <sub tlv> */
1416                 long len_offset;
1417                 long off_start;
1418                 long off_stop;
1419                 /* </sub tlv> */
1420                 memcpy(&tmp_cv, cv, sizeof(tmp_cv));
1421                 tmp_cv.tab[0] = p->include;
1422                 
1423                 /* <sub tlv> */
1424                 /* This is sub tlv/ thus put tag... */
1425                 if (EXSUCCEED!=ndrx_write_tag((short)p->tag, proto_buf, 
1426                         proto_buf_offset, proto_bufsz))
1427                 {
1428                     EXFAIL_OUT(ret);
1429                 }
1430                 
1431                 NDRX_LOG(log_debug, "XINC tag: 0x%x, current offset=%ld, new=%ld", 
1432                         p->tag, offset, p->offset);
1433                 
1434                 len_offset = *proto_buf_offset;
1435                 CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, LEN_BYTES);
1436                 *proto_buf_offset=*proto_buf_offset+LEN_BYTES;
1437                 
1438                 off_start = *proto_buf_offset; /* why not +2??? */
1439                 /* </sub tlv> */
1440                 
1441                 /* If we use include the we should go deeper inside, not? */
1442                 ret = exproto_build_ex2proto(&tmp_cv, 0, offset+p->offset,
1443                         ex_buf, ex_len, proto_buf, proto_buf_offset, NULL, NULL, 
1444                         proto_bufsz);
1445                 
1446                 if (EXSUCCEED!=ret)
1447                 {
1448                     NDRX_LOG(log_error, "Failed to convert sub/tag %x: [%s] %ld"
1449                             "at offset %ld", p->tag, p->cname, p->offset);
1450                     ret=EXFAIL;
1451                     goto out;
1452                 }
1453                 
1454                 /* <sub tlv> */
1455                 off_stop = *proto_buf_offset;
1456                 /* Put back len there.. */
1457                 len_written = (int)(off_stop - off_start);
1458                 
1459                 NDRX_LOG(log_debug, "len_written=%d len_offset=%ld", 
1460                         len_written, len_offset);
1461                 
1462                 if (EXSUCCEED!=ndrx_write_len(len_written, proto_buf, &len_offset, 
1463                         proto_bufsz))
1464                 {
1465                     EXFAIL_OUT(ret);
1466                 }
1467                 /* </sub tlv> */
1468             }
1469                 break;
1470             case XLOOP:
1471             {
1472                 xmsg_t tmp_cv;
1473                 
1474                 memcpy(&tmp_cv, cv, sizeof(tmp_cv));
1475                 tmp_cv.tab[0] = p->include;
1476                 
1477                 int *count = (int *)(ex_buf+offset+p->counter_offset);
1478                 int j;
1479                 
1480                 NDRX_LOG(log_info, "Serialising: %d elements, "
1481                         "current tag: 0x%x", *count, p->tag);
1482                 
1483                 for (j=0; j<*count && EXSUCCEED==ret; j++)
1484                 {
1485                     
1486                     /* Reserve space for Tag/Length */
1487                     /* <sub tlv> */
1488                     long len_offset;
1489                     long off_start;
1490                     long off_stop;
1491 
1492                     /* This is sub tlv/ thus put tag... */
1493                     if (EXSUCCEED!=ndrx_write_tag((short)p->tag, proto_buf, 
1494                             proto_buf_offset, proto_bufsz))
1495                     {
1496                         EXFAIL_OUT(ret);
1497                     }
1498                     
1499                     len_offset = *proto_buf_offset;
1500                     
1501                     CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, LEN_BYTES);
1502                     *proto_buf_offset=*proto_buf_offset+LEN_BYTES;
1503                     
1504                     off_start = *proto_buf_offset;
1505                     /* </sub tlv> */
1506                     
1507                     ret = exproto_build_ex2proto(&tmp_cv, 0, 
1508                                 offset+p->offset + p->elem_size*j,
1509                                 ex_buf, ex_len, proto_buf, proto_buf_offset,
1510                                 NULL, NULL, proto_bufsz);
1511                     
1512                     if (EXSUCCEED!=ret)
1513                     {
1514                         NDRX_LOG(log_error, "Failed to convert "
1515                                 "sub/tag %x: [%s] %ld"
1516                                 "at offset %ld", 
1517                                 p->tag, p->cname, p->offset);
1518                         ret=EXFAIL;
1519                         goto out;
1520                     }
1521                     
1522                     /* <sub tlv> */
1523                     off_stop = *proto_buf_offset;
1524                     /* Put back len there.. */
1525                     len_written = (int)(off_stop - off_start);
1526                     
1527                     if (EXSUCCEED!=ndrx_write_len(len_written, proto_buf, &len_offset,
1528                             proto_bufsz))
1529                     {
1530                         EXFAIL_OUT(ret);
1531                     }
1532                     /* </sub tlv> */
1533                 }
1534                 
1535             }
1536                 break;
1537                 
1538             case XMASTERBUF:
1539                 
1540                 NDRX_LOG(log_debug, "Enter into master buffer out");
1541                 
1542                 if (EXSUCCEED!=exproto_build_ex2proto_mbuf(p, level, offset,
1543                             ex_buf, ex_len, proto_buf, proto_buf_offset,
1544                                 accept_tags, p_ub_data, proto_bufsz))
1545                 {
1546                     EXFAIL_OUT(ret);
1547                 }
1548                 
1549                 break;
1550             case XATMIBUFPTR:
1551             case XATMIBUF:
1552             {
1553                 /* This is special driver for ATMI buffer */
1554                 long *buf_len = (long *)(ex_buf+offset+p->counter_offset);
1555                 char *data;
1556                 int f_type;
1557                 long len_offset;
1558                 long off_start;
1559                 long off_stop;
1560                 unsigned buffer_type;
1561                 
1562                 if (XATMIBUFPTR==XTYPE(p->type))
1563                 {
1564                     BFLDID *p_fldid = (BFLDID*)(ex_buf+offset+p->buftype_offset);
1565                     int typ = Bfldtype(*p_fldid);
1566                     
1567                     if (BFLD_UBF == typ)
1568                     {
1569                         buffer_type = BUF_TYPE_UBF;
1570                     }
1571                     else if (BFLD_VIEW == typ)
1572                     {
1573                         buffer_type = BUF_TYPE_VIEW;
1574                     }
1575                     else
1576                     {
1577                         NDRX_LOG(log_debug, "Invalid sub-xatmi buffer field type %d",
1578                                 typ);
1579                         EXFAIL_OUT(ret);
1580                     }
1581                         
1582                     /* dereference stored pointer */
1583                     data = *((char **)(ex_buf+offset+p->offset));
1584                 }
1585                 else
1586                 {
1587                     buffer_type = *((unsigned*)(ex_buf+offset+p->buftype_offset));
1588                     
1589                     data = (char *)(ex_buf+offset+p->offset);
1590                     
1591                     buffer_type = NDRX_MBUF_TYPE(buffer_type);
1592                 }
1593                 
1594                 NDRX_LOG(log_debug, "Buffer type is: %u", 
1595                         buffer_type);
1596                 
1597                 /* TAG START / KEEP POS */
1598                 if (EXSUCCEED!=ndrx_write_tag((short)p->tag, proto_buf, 
1599                         proto_buf_offset, proto_bufsz))
1600                 {
1601                     EXFAIL_OUT(ret);
1602                 }
1603                 len_offset = *proto_buf_offset;
1604                 CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, LEN_BYTES);
1605                 *proto_buf_offset=*proto_buf_offset+LEN_BYTES;
1606                 off_start = *proto_buf_offset;
1607                 /* TAG START / KEEP POS (END) */
1608                 
1609                 if (BUF_TYPE_UBF==buffer_type)
1610                 {
1611                     UBFH *p_ub = (UBFH *)data;
1612                     Bnext_state_t state;
1613                     char f_data_buf[sizeof(proto_ufb_fld_t)+sizeof(char *)]; /* just store ptr */
1614                     ssize_t f_data_buf_len;
1615                     proto_ufb_fld_t *f;
1616                     BFLDOCC occ;
1617                     
1618                     short accept_tags[] = {UBF_TAG_BFLDID, 0, EXFAIL};
1619                     
1620                     /* Reserve space for Tag/Length */
1621                     /* <sub tlv> */
1622                     xmsg_t tmp_cv;
1623                     
1624                     /* as we store here pointers only  */
1625                     
1626                     f_data_buf_len = sizeof(f_data_buf);
1627                     f =  (proto_ufb_fld_t *)f_data_buf;
1628                     
1629                     /* </sub tlv> */
1630                     memcpy(&tmp_cv, cv, sizeof(tmp_cv));
1631                     tmp_cv.descr = "UBFFLD";
1632                     tmp_cv.tab[0] = M_ubf_field;
1633 
1634                     /* <process field by field> */
1635                     NDRX_LOG(log_debug, "Processing UBF buffer");
1636                     
1637                     /* loop over the buffer & process field by field */
1638                     /*memset(f.buf, 0, sizeof(f.buf));  <<< HMMM Way too slow!!! */
1639                     
1640                     f->bfldlen = 0;
1641                     f->bfldid = BFIRSTFLDID;
1642                     
1643                     memset(&state, 0, sizeof(state));
1644                     
1645                     while(1==ndrx_Bnext(&state, p_ub, &f->bfldid, &occ, NULL, &f->bfldlen, (char **)&f->buf))
1646                     {
1647                         f_type = Bfldtype(f->bfldid);
1648                         
1649                         /* Optimize out the length field for fixed
1650                          * data types
1651                          */
1652                         accept_tags[1] = ndrx_G_ubf_proto_tag_map[f_type];
1653 
1654                         /* lets drive our structure? */
1655                         ret = exproto_build_ex2proto(&tmp_cv, 0, 0,
1656                             (char *)f, f_data_buf_len, proto_buf, 
1657                             proto_buf_offset,  accept_tags, f, proto_bufsz);
1658                     
1659                         if (EXSUCCEED!=ret)
1660                         {
1661                             NDRX_LOG(log_error, "Failed to convert "
1662                                     "sub/tag %x: [%s] %ld"
1663                                     "at offset %ld", 
1664                                     p->tag, p->cname, p->offset);
1665                             EXFAIL_OUT(ret);
1666                         }
1667                         
1668                         f->bfldlen = 0;
1669                     }
1670                     
1671                     /* </process field by field> */
1672                     /*NDRX_SYSBUF_FREE(f_data_buf);*/
1673                 }
1674                 else if (BUF_TYPE_VIEW==buffer_type)
1675                 {
1676                     NDRX_LOG(log_debug, "Converting view out");
1677                     
1678                     if (EXSUCCEED!=(ret=exproto_build_ex2proto_view(p, 0, 0,
1679                         data, 0, proto_buf, proto_buf_offset, proto_bufsz)))
1680                     {
1681                         NDRX_LOG(log_error, "Failed to serialize VIEW %d", ret);
1682                         EXFAIL_OUT(ret);
1683                     }
1684                     
1685                 }    
1686                 else
1687                 {
1688                     /* Should work for string buffers too, if EOS counts in len! */
1689                     NDRX_LOG(log_debug, "Processing data block buffer");                    
1690                     /* Put data on network */
1691                     CHECK_PROTO_BUFSZ(ret, *proto_buf_offset, proto_bufsz, *buf_len);
1692                     memcpy(proto_buf+(*proto_buf_offset), data, *buf_len);
1693                     *proto_buf_offset=*proto_buf_offset + *buf_len;
1694                 }
1695                 
1696                 /* <sub tlv - common lenght (real data) > */
1697                 off_stop = *proto_buf_offset;
1698                 /* Put back len there.. */
1699                 len_written = (int)(off_stop - off_start);
1700                 if (EXSUCCEED!=ndrx_write_len(len_written, proto_buf, &len_offset,
1701                         proto_bufsz))
1702                 {
1703                     EXFAIL_OUT(ret);
1704                 }
1705                 /* </sub tlv> */
1706 
1707                 
1708             }
1709                 break;
1710                 /* case ATMIBUF is processed as part of master buffer  */
1711         }
1712         
1713         /* Verify data length (currently at warning level!) - it should be
1714          * in range!
1715          */
1716         /* Feature #127 2017/10/16 Allow dynamic max buffer size configuration */
1717         max_len = p->max_len;
1718         if (PMSGMAX == max_len)
1719         {
1720             max_len = NDRX_MSGSIZEMAX;
1721         }
1722         
1723         /* check the generated len finally */
1724         if (EXFAIL==exproto_cklen(p, len_written, proto_buf+(*proto_buf_offset) - len_written))
1725         {
1726             NDRX_LOG(log_error, "Bridge protocol error: Invalid network data has been generated");
1727             userlog("Bridge protocol error: Invalid network data has been generated");
1728             EXFAIL_OUT(ret);
1729         }
1730         
1731 tag_continue:
1732         p++;
1733     }
1734 out:
1735     NDRX_LOG(log_debug, "Return %d level %d", ret, level);
1736 
1737     return ret;
1738 }
1739 
1740 /**
1741  * Convert Enduro/X internal format to Network Format.
1742  * @param ex_buf Enduro/X data buffer machine dependent, C struct
1743  * @param ex_len data len of the C struct
1744  * @param proto_buf where to serialize the data
1745  * @param proto_len output len 
1746  * @param proto_bufsz output buffer size
1747  * @return EXSUCCEED/EXFAIL
1748  */
1749 expublic int exproto_ex2proto(char *ex_buf, long ex_len, char *proto_buf, 
1750         long *proto_len, long proto_bufsz)
1751 {
1752     int ret=EXSUCCEED;
1753     /* Identify the message */
1754     cmd_br_net_call_t *msg = (cmd_br_net_call_t *)ex_buf;
1755     char *fn = "exproto_ex2proto";
1756     xmsg_t *cv;
1757     
1758     /* Field used in search: */
1759     char msg_type=0; /* Identify our message type... */
1760     int     command=EXFAIL;
1761     /* /Field used in search: */
1762     
1763     NDRX_LOG(log_debug, "%s - enter", fn);
1764     
1765     switch (msg->msg_type)
1766     {
1767         case BR_NET_CALL_MSG_TYPE_ATMI:
1768             /* This is NDRXD message */
1769         {
1770             tp_command_generic_t *call = *(tp_command_generic_t **)msg->buf;
1771             command = call->command_id;
1772             msg_type = 'A';
1773         }
1774             break;
1775         case BR_NET_CALL_MSG_TYPE_NDRXD:
1776             /* This is ATMI message */
1777         {
1778             command_call_t *call = *((command_call_t **)msg->buf);
1779             
1780             msg_type = 'X';
1781             command = call->command;
1782             
1783         }
1784             break;
1785         case BR_NET_CALL_MSG_TYPE_NOTIF:
1786             /* This is NDRXD message */
1787         {
1788             tp_command_generic_t *call = *(tp_command_generic_t **)msg->buf;
1789             command = call->command_id;
1790             msg_type = 'N';
1791         }
1792             break;
1793     }
1794     
1795     cv = M_ndrxd_x;
1796     /* OK, we should pick up the table and start to conv. */
1797     while (EXFAIL!=cv->command)
1798     {
1799 
1800         if ((msg_type == cv->msg_type && command == cv->command)
1801                 /* Accept any ATMI - common structure! */
1802                 || (msg_type == cv->msg_type && 'A' == msg_type )
1803                 )
1804         {
1805             NDRX_LOG(log_debug, "Found conv table for: %c/%d/%s", 
1806                     cv->msg_type, cv->command, cv->descr);
1807 
1808             ret = exproto_build_ex2proto(cv, 0, 0, ex_buf, ex_len, 
1809                     proto_buf, proto_len, NULL, NULL, proto_bufsz);
1810 
1811             break;
1812         }
1813         cv++;
1814     }
1815 
1816     if (EXFAIL==cv->command)
1817     {
1818         NDRX_LOG(log_error, "No conv table for ndrxd command: %c/%d"
1819                 " - FAIL", msg_type, command);
1820         ret=EXFAIL;
1821         goto out;
1822     }
1823     
1824     
1825 out:
1826    
1827     NDRX_LOG(log_debug, "%s - returns %d", fn, ret);
1828     return ret;
1829 }
1830 
1831 
1832 /**
1833  * Search field from tag...
1834  * @param cur
1835  * @param tag
1836  * @return 
1837  */
1838 exprivate inline cproto_t * get_descr_from_tag(cproto_t *cur, short tag)
1839 {
1840    int first, last, middle;
1841    int search = tag;
1842    int n = M_ptinfo[cur->tableid].dim-1; /* skip the FAIL (last) */
1843  
1844    first = 0;
1845    last = n - 1;
1846    middle = (first+last)/2;
1847  
1848    while (first <= last)
1849    {
1850       if (cur[middle].tag < search)
1851       {
1852          first = middle + 1;    
1853       }
1854       else if (cur[middle].tag == search)
1855       {
1856           return &cur[middle];
1857       }
1858       else
1859       {
1860          last = middle - 1;
1861       }
1862       
1863       middle = (first + last)/2;
1864    }
1865    if (first > last)
1866    {
1867       NDRX_LOG(log_debug, "tag %x not found in table %d.\n", 
1868               search, cur->tableid);
1869    }
1870    
1871    return NULL;   
1872 }
1873 
1874 /**
1875  * Entry point from deblock of network message.
1876  * @param proto_buf
1877  * @param proto_len
1878  * @param ex_buf
1879  * @param ex_offs current offset in C struct
1880  * @param max_struct
1881  * @param ex_bufsz - Enduro/X output buffer size
1882  * @return EXSUCCED/EXFAIL
1883  */
1884 expublic int exproto_proto2ex(char *proto_buf, long proto_len, 
1885         char *ex_buf, long *max_struct, long ex_bufsz)
1886 {
1887     *max_struct = 0;
1888     return _exproto_proto2ex(M_cmd_br_net_call_x, proto_buf, proto_len,
1889         ex_buf, 0, max_struct, 0, NULL, NULL, ex_bufsz);
1890 }
1891 
1892 /**
1893  * Deblock the network message...
1894  * Hm Also we need to get total len of message, in c structure?
1895  * @param ex_buf - Enduro/X machine specific C strutures data
1896  * @param ex_offset - current offset of the processing structure (not the current
1897  *  field). Current field is set in int_pos
1898  * @param proto_buf - procol received from net
1899  * @param proto_len - block len received
1900  * @param ex_bufsz buffer size for c block
1901  * @return EXFAIL or current offset in parsed buf
1902  */
1903 expublic long _exproto_proto2ex(cproto_t *cur, char *proto_buf, long proto_len, 
1904         char *ex_buf, long ex_offset, long *max_struct, int level, 
1905         char *p_typedbuf, proto_ufb_fld_t *p_ub_data, long ex_bufsz)
1906 {
1907     int ret=EXSUCCEED;
1908     xmsg_t *cv = NULL;
1909     /* Current conv table: */
1910     cproto_t *fld = NULL;
1911     
1912     short net_tag;
1913     int net_len;
1914     int loop_keeper = 0;
1915     long int_pos = 0;
1916     int  *p_fld_len;
1917     int  xatmi_fld_len;
1918     int max_len;
1919     char debug[16*1024];
1920     tp_command_call_t *more_debug;
1921     /* temp buf for UBF processing */
1922     char *tmpf = NULL;
1923     size_t tmpf_len;
1924     proto_ufb_fld_t *f;
1925     proto_ufb_fld_t tmpdata; /* temporary field infos storage */
1926     int done=EXFALSE;
1927 
1928     tmpdata.bfldid=0;
1929     tmpdata.bfldlen=0;
1930 
1931     NDRX_LOG(log_debug, "Enter field: [%s] max_struct: %ld ex_buf: %p", 
1932                         cur->cname, *max_struct, ex_buf);
1933     
1934     NDRX_DUMP(log_debug, "_exproto_proto2ex enter", 
1935                     proto_buf, proto_len);
1936     
1937     /* +2 is tag +  4 is len ... thus that is minimum read. */
1938     while (int_pos+6 <= proto_len && !done)
1939     {
1940         /* Read tag */
1941         /* Check that we have enough positions to read... */
1942         
1943         net_tag = read_net_short(proto_buf, &int_pos);
1944         
1945         /* Read len */
1946         net_len = read_net_int(proto_buf, &int_pos);
1947         
1948         if (net_len < 0)
1949         {
1950             /* this is invalid lens */
1951             NDRX_LOG(log_error, "ERROR: Invalid data len <0 - FAIL");
1952             EXFAIL_OUT(ret);
1953         }
1954         
1955         if (net_len > proto_len - int_pos)
1956         {
1957             NDRX_LOG(log_error, "ERROR: Invalid length - larger than buffer left: net_len: %d, left: %d",
1958                     net_len, proto_len - int_pos);
1959             EXFAIL_OUT(ret);
1960         }
1961         
1962         /*
1963         NDRX_LOG(log_debug, "Got tag: %x, got len: %x (%hd)", 
1964                 net_tag, net_len, net_len);
1965         */
1966         /* We should understand now what this type of field is...? */
1967         fld = get_descr_from_tag(cur, net_tag);
1968         
1969         if (NULL==fld)
1970         {
1971             NDRX_LOG(log_warn, "No descriptor for tag: %x - SKIP!", 
1972                     net_tag);
1973         }
1974         else
1975         {
1976             p_fld_len = &fld->len;
1977          /*   NDRX_LOG(log_debug, "Processing field.... [%s]", fld->cname);*/
1978             
1979             /* Verify data length (currently at warning level!) - it should be
1980              * in range!
1981              */
1982             max_len = fld->max_len;
1983             
1984             /* Feature #127 - Allow dynamic max buffer size configuration */
1985             if (PMSGMAX == max_len)
1986             {
1987                 max_len = NDRX_MSGSIZEMAX;
1988             }
1989 
1990             /* validate that we got valid record in length */
1991             if (EXFAIL==exproto_cklen(fld, net_len, (proto_buf+int_pos)))
1992             {
1993                 NDRX_LOG(log_error, "Bridge protocol error: Invalid network data has been received");
1994                 EXFAIL_OUT(ret);
1995             }
1996 
1997             switch (XTYPE(fld->type))
1998             {
1999                 case XFLDPTR:
2000                 case XFLD:
2001                 case XSBL:
2002                 {
2003                     BFLDLEN bfldlen = 0; /* Default zero, used for carray! */
2004                     loop_keeper = 0;
2005                     
2006                     if (EXSUCCEED!=x_nettoc(fld, proto_buf, int_pos, net_len, 
2007                             (char *)(ex_buf+ex_offset+fld->offset), &bfldlen, 
2008                             debug, sizeof(debug), (ex_bufsz - (ex_offset+fld->offset))))
2009                     {
2010                         NDRX_LOG(log_error, "Failed to convert from net"
2011                                 " tag: %x!", net_tag);
2012                         ret=EXFAIL;
2013                         goto out;
2014                     }
2015                     
2016                     if (NULL!=p_ub_data && ( 
2017                             UBF_TAG_BFLD_SHORT <= net_tag &&
2018                             UBF_TAG_BFLD_PTR >= net_tag))
2019                     {
2020                         
2021                         NDRX_LOG(log_debug, "Installing FB field: "
2022                                 "id=%d, len=%d", p_ub_data->bfldid, bfldlen);
2023                         
2024                         /* empty strings????? & data not reset? */                        
2025                         if (EXSUCCEED!=Baddfast((UBFH *)p_typedbuf, p_ub_data->bfldid, 
2026                                 p_ub_data->buf, bfldlen, &p_ub_data->next_fld))
2027                         {
2028                             NDRX_LOG(log_error, "Failed to setup field %s:%s",
2029                                     Bfname(p_ub_data->bfldid), Bstrerror(Berror));
2030                             
2031                             ret=EXFAIL;
2032                             goto out;
2033                         }
2034                     }
2035                     else if (NULL!=p_ub_data && ( 
2036                             VIEW_TAG_SHORT <= net_tag &&
2037                             VIEW_TAG_INT >= net_tag))
2038                     {
2039                         ndrx_typedview_field_t *vf = NULL;
2040                         BFLDOCC occ;
2041                         
2042                         if (NULL==p_ub_data->v)
2043                         {
2044                             userlog("Error: View data not expected for null views got cname=[%s]", 
2045                                     p_ub_data->cname);
2046                             NDRX_LOG(log_error, "Error: View data not expected for null views got cname=[%s]", 
2047                                     p_ub_data->cname);
2048                             EXFAIL_OUT(ret);
2049                         }
2050                         
2051                         if (NULL==(vf = ndrx_view_get_field(p_ub_data->v, p_ub_data->cname)))
2052                         {
2053                             NDRX_LOG(log_warn, "Field [%s] of view [%s] not found - ignore", 
2054                                     p_ub_data->cname, p_ub_data->v->vname);
2055                         }
2056                         else
2057                         {
2058                             /* Load the view field */
2059                             occ = ndrx_viewocc_get(&p_ub_data->vocc, p_ub_data->cname);
2060                             
2061                             if (EXFAIL==occ)
2062                             {
2063                                 NDRX_LOG(log_error, "Malloc failed to cname=[%s] view [%s] occ",
2064                                         p_ub_data->cname, p_ub_data->v->vname);
2065                                 userlog("Malloc failed to cname=[%s] view [%s] occ",
2066                                         p_ub_data->cname, p_ub_data->v->vname);
2067                                 EXFAIL_OUT(ret);
2068                             }
2069                             
2070                             /* Load that field finally!
2071                              * Map the initial type OK!
2072                              */
2073                             if (EXSUCCEED!=(ret=ndrx_CBvchg_int(p_typedbuf, 
2074                                     p_ub_data->v, vf, occ, p_ub_data->buf, bfldlen, 
2075                                     /* last 4 bits are type id */
2076                                     (net_tag & 0x0f) )))
2077                             {
2078                                 EXFAIL_OUT(ret);
2079                             }
2080                         }
2081                     }
2082                     
2083                     NDRX_LOG(log_debug, "net2ex: tag: [0x%x]\t[%s]\t len: %ld (0x%04lx) type:"
2084                         " [%s]\t data: [%s]"/*" netbuf (data start): %p"*/, 
2085                         net_tag, fld->cname, net_len, net_len, M_type[fld->fld_type], 
2086                             debug/*, (proto_buf+int_pos)*/ );
2087                 }
2088                     break;
2089                 case XSUBPTR:
2090                 case XSUB:
2091                 {
2092                     loop_keeper = 0;
2093                     NDRX_LOG(log_debug, "XSUB");
2094                     /* This uses sub-table, lets request function to 
2095                      * find out the table! 
2096                      */
2097                     if (NULL==(cv = fld->p_classify_fn(ex_buf, ex_offset)))
2098                     {
2099                         /* We should have something! */
2100                         ret=EXFAIL;
2101                         goto out;
2102                     }
2103                     else
2104                     {
2105                         if (EXFAIL==_exproto_proto2ex(cv->tab[level+1], 
2106                                     (char *)(proto_buf+int_pos), net_len, 
2107                                     ex_buf, ex_offset+fld->offset,
2108                                     max_struct, level+1, NULL, NULL, ex_bufsz))
2109                         {
2110                             EXFAIL_OUT(ret);
2111                         }
2112                     }
2113                     
2114                     
2115                     /* If there is length indicator available, restore it... */
2116                     
2117                     if (fld->counter_offset>EXFAIL)
2118                     {
2119                         long *buf_len = (long *)(ex_buf+ex_offset+fld->counter_offset);
2120                         *buf_len = *max_struct - fld->offset;
2121                         NDRX_LOG(log_debug, "Restored len: %ld", *buf_len);
2122                     }
2123                     
2124                 }
2125                     break;
2126                     
2127                 case XINC:
2128                 {
2129                     loop_keeper = 0;
2130                     NDRX_LOG(log_debug, "XINC");
2131                     /* Go level deeper & use included table */
2132                     
2133                     if (EXFAIL==_exproto_proto2ex(fld->include, 
2134                                     (char *)(proto_buf+int_pos), net_len, 
2135                                     ex_buf, ex_offset+fld->offset,
2136                                     max_struct, level+1, NULL, NULL, ex_bufsz))
2137                     {
2138                         EXFAIL_OUT(ret);
2139                     }
2140 
2141                     
2142                     NDRX_LOG(log_debug, "return from XINC...");
2143                 }
2144                     break;
2145                     
2146                 case XLOOP:
2147                 {
2148                     NDRX_LOG(log_debug, "XLOOP, array elem: %d", 
2149                             loop_keeper);
2150                     if (EXFAIL==_exproto_proto2ex(fld->include, 
2151                                     (char *)(proto_buf+int_pos), net_len, 
2152                                     ex_buf, (ex_offset+fld->offset + fld->elem_size*loop_keeper),
2153                                     max_struct, level+1, NULL, NULL, ex_bufsz))
2154                     {
2155                         EXFAIL_OUT(ret);
2156                     }
2157 
2158                     loop_keeper++;
2159                 }
2160                     break;
2161 
2162                 case XMASTERBUF:
2163                 {
2164                     NDRX_LOG(log_debug, "Enter into master buffer in");
2165 
2166                     /* as we loop over the several MBUFs,
2167                      * we need to update the net len too... */
2168                     if (EXFAIL==_exproto_proto2ex_mbuf(fld, 
2169                             (char *)(proto_buf+int_pos), net_len, 
2170                             ex_buf, ex_offset, max_struct, level, 
2171                             NULL, &tmpdata, ex_bufsz))
2172                     {
2173                         EXFAIL_OUT(ret);
2174                     }
2175                 }   
2176                 break;                    
2177                 case XATMIBUFPTR:
2178                 case XATMIBUF:
2179                 {
2180                     long *buf_len = (long *)(ex_buf+ex_offset+fld->counter_offset);
2181                     char *data = (char *)(ex_buf+ex_offset+fld->offset);
2182                     unsigned buffer_type;
2183                     
2184                     /* PTR is used only by sub-UBF fields */
2185                     if (XATMIBUFPTR==XTYPE(fld->type))
2186                     {
2187                         BFLDID *p_fldid = (BFLDID*)(ex_buf+ex_offset+fld->buftype_offset);
2188                         int typ = Bfldtype(*p_fldid);
2189                         
2190                         if (BFLD_UBF == typ)
2191                         {
2192                             buffer_type = BUF_TYPE_UBF;
2193                         }
2194                         else if (BFLD_VIEW == typ)
2195                         {
2196                             buffer_type = BUF_TYPE_VIEW;
2197                         }
2198                         else
2199                         {
2200                             NDRX_LOG(log_error, "Invalid sub-XATMI buffer field type: %d", 
2201                                     typ);
2202                             EXFAIL_OUT(ret);
2203                         }
2204                     }
2205                     else
2206                     {
2207                         unsigned *p_buffer_type = (unsigned*)(ex_buf+ex_offset+fld->buftype_offset);
2208                         buffer_type = NDRX_MBUF_TYPE(*p_buffer_type);
2209                     }
2210                     
2211                     NDRX_LOG(log_debug, "Processing XATMIBUF type: %u", buffer_type);
2212                     
2213                     /* will be freed on loop end or exit */
2214                     NDRX_SYSBUF_MALLOC_OUT(tmpf, tmpf_len, ret);
2215     
2216                     f=(proto_ufb_fld_t *)tmpf;
2217                     
2218                     /* reset the header */
2219                     memset(tmpf, 0, sizeof(proto_ufb_fld_t));
2220                     
2221                     
2222                     if (buffer_type == BUF_TYPE_UBF)
2223                     {   
2224                         UBFH *p_ub = (UBFH *)(ex_buf+ex_offset+fld->offset);
2225                         UBF_header_t *hdr  = (UBF_header_t *)p_ub;
2226                         int tmp_buf_size = /*PMSGMAX*/ex_bufsz - ex_offset - fld->offset;
2227 
2228                         
2229                         NDRX_DUMP(log_debug, "Got UBF buffer", 
2230                                 (char *)(proto_buf+int_pos), net_len);
2231                                                 /* 
2232                          * Init the FB to max possible size, then we will reduce OK!?
2233                          */
2234                         NDRX_LOG(log_debug, "Initial FB size: %d (p_ub=%p "
2235                                 "(ex_buf %p + ex_len %ld + fld->offset %ld))", 
2236                                 tmp_buf_size, p_ub, ex_buf, ex_offset, fld->offset);
2237                         
2238                         if (EXSUCCEED!=Binit(p_ub, tmp_buf_size))
2239                         {
2240                             NDRX_LOG(log_error, "Failed to init FB: %s", 
2241                                     Bstrerror(Berror) );
2242                             ret=EXFAIL;
2243                             goto out;
2244                         }
2245                         
2246                         /* OK, we have a FB now process field by field...? */
2247                         
2248                         if (EXFAIL==_exproto_proto2ex(M_ubf_field,  
2249                                     (char *)(proto_buf+int_pos), net_len, 
2250                                     /* Drive over internal variable + we should 
2251                                      * have callback when data completed, so that
2252                                      * we can install them in FB! */
2253                                     (char *)f, 0,
2254                                     max_struct, level,
2255                                     (char *)p_ub, f, tmpf_len))
2256                         {
2257                             EXFAIL_OUT(ret);
2258                         }
2259                         
2260                         if (EXSUCCEED!=ret)
2261                         {
2262                             NDRX_FPFREE(tmpf);
2263                             tmpf=NULL;
2264                             f=NULL;
2265                             goto out;
2266                         }
2267                         
2268                         /* Resize FB? */
2269                         hdr->buf_len = hdr->bytes_used;
2270                         
2271                         xatmi_fld_len = hdr->buf_len;
2272                         p_fld_len = &xatmi_fld_len;
2273                         
2274                         *buf_len = hdr->buf_len;
2275                                 
2276                         /* Bprint(p_ub); Bug #120 */
2277             ndrx_debug_dump_UBF(log_debug, "Restored buffer", p_ub);
2278                         
2279                         /*  have some debug */
2280                         more_debug = 
2281                             (tp_command_call_t *)(ex_buf + sizeof(cmd_br_net_call_t));
2282 
2283                         if (ATMI_COMMAND_TPCALL == more_debug->command_id || 
2284                                 ATMI_COMMAND_CONNECT == more_debug->command_id)
2285                         {
2286                             NDRX_LOG(log_debug, "timer = (%ld %ld) %d", 
2287                                     more_debug->timer.t.tv_sec, 
2288                                     more_debug->timer.t.tv_nsec,
2289                                     ndrx_stopwatch_get_delta_sec(&more_debug->timer));
2290                             NDRX_LOG(log_debug, "callseq  %u", 
2291                                     more_debug->callseq);
2292                             NDRX_LOG(log_debug, "cd  %d", 
2293                                     more_debug->cd);
2294                             NDRX_LOG(log_debug, "my_id  [%s]", 
2295                                     more_debug->my_id);
2296                             NDRX_LOG(log_debug, "reply_to  [%s]", 
2297                                     more_debug->reply_to);
2298                             NDRX_LOG(log_debug, "name  [%s]", 
2299                                     more_debug->name);
2300                         }
2301                         
2302                         /**
2303                          * if there was master UBF present, then this
2304                          * is inner buffer... thus add the field.
2305                          * optimization: addfast
2306                          */
2307                         if (NULL!=p_typedbuf)
2308                         {
2309                             /* buf is current field offset */
2310                             if (EXSUCCEED!=Baddfast((UBFH *)p_typedbuf, p_ub_data->bfldid, 
2311                                     p_ub_data->buf, 0, &p_ub_data->next_fld))
2312                             {
2313                                 NDRX_LOG(log_error, "Failed to setup field %s:%s",
2314                                         Bfname(p_ub_data->bfldid), Bstrerror(Berror));
2315                                 ret=EXFAIL;
2316                                 goto out;
2317                             }
2318                         }
2319                         
2320                     }
2321                     else if (BUF_TYPE_VIEW==buffer_type)
2322                     {
2323                         /* for XATMIBUFPTR header is BVIEWFLD */
2324                         /* for XATMIBUF header is ndrx_view_header */
2325                         
2326                         /* Firstly we need to extract the header infos
2327                          * then we can start to restore the view
2328                          */
2329                         long tmpret;
2330                         BVIEWFLD vheader; /* read header tags */
2331                         char *vdata;
2332                         BVIEWFLD *vf;
2333                         
2334                         memset(&vheader, 0, sizeof(vheader));
2335                         
2336                         if (EXFAIL==(tmpret=_exproto_proto2ex(ndrx_G_view,
2337                                     (char *)(proto_buf+int_pos), net_len, 
2338                                     (char *)&vheader, 0,
2339                                     max_struct, 0,
2340                                     NULL, NULL, tmpf_len)))
2341                         {
2342                             EXFAIL_OUT(ret);
2343                         }
2344                         
2345                         NDRX_LOG(log_debug, "Deserialize view: [%s] (header len: %ld)", 
2346                                 vheader.vname, tmpret);
2347                         
2348                         /* OK, read next, if have anything... */
2349                         
2350                         if (XATMIBUFPTR==XTYPE(fld->type))
2351                         {
2352                             /* we are part of UBF... */
2353                             vf =(BVIEWFLD *)(ex_buf + ex_offset+fld->offset);
2354                             NDRX_STRCPY_SAFE(vf->vname, vheader.vname);
2355                             vf->vflags = vheader.vflags;
2356                             
2357                             /* prepare field offset -> temp space should
2358                              * have enough space for header, thus no checking here
2359                              */
2360                             vf->data = (ex_buf + ex_offset + sizeof(BVIEWFLD));
2361                             vdata = vf->data;
2362                         }
2363                         else
2364                         {
2365                             /* we work with clean FB */
2366                             ndrx_view_header * p_hdr = (ndrx_view_header *)(ex_buf + ex_offset+fld->offset);
2367                             /* data buffer unload */
2368                             CHECK_EX_BUFSZ(ret, ex_offset, EXOFFSET(ndrx_view_header, vname), 
2369                                     ex_bufsz, (NDRX_VIEW_NAME_LEN+1));
2370                             NDRX_STRCPY_SAFE(p_hdr->vname, vheader.vname);
2371                             
2372                             CHECK_EX_BUFSZ(ret, ex_offset, EXOFFSET(ndrx_view_header, vflags), 
2373                                     ex_bufsz, sizeof(unsigned int));
2374                             p_hdr->vflags = vheader.vflags;
2375                             
2376                             CHECK_EX_BUFSZ(ret, ex_offset, EXOFFSET(ndrx_view_header, cksum), 
2377                                     ex_bufsz, sizeof(uint32_t));
2378                             p_hdr->cksum  = 0;
2379                             
2380                             /* static array addr is OK */
2381                             vdata = p_hdr->data;
2382                         }
2383                         
2384                         /* Start to drive the view fields
2385                          * have another f
2386                          * the field functions shall detect that we work
2387                          * with view, thus use View add funcs.
2388                          * Also the hashmap needs to be driven for counting
2389                          * the field occurrences.
2390                          */
2391                         
2392                         /* resolve view */
2393                         if (EXEOS!=vheader.vname[0])
2394                         {
2395 
2396                             f->v = ndrx_view_get_init(vheader.vname);
2397 
2398                             if (NULL==f->v)
2399                             {
2400                                 NDRX_LOG(log_error, "VIEW [%s] NOT FOUND!", vheader.vname);
2401                                 userlog("ERROR ! VIEW [%s] NOT FOUND!", vheader.vname);
2402                                 EXFAIL_OUT(ret);
2403                             }
2404                             
2405                             if (EXFAIL==Bvsinit(vdata, vheader.vname))
2406                             {
2407                                 NDRX_LOG(log_error, "Failed to init view [%s] at %p: %s", 
2408                                         vheader.vname, vdata, Bstrerror(Berror));
2409                                 userlog("Failed to init view [%s] at %p: %s", 
2410                                         vheader.vname, vdata, Bstrerror(Berror));
2411                                 EXFAIL_OUT(ret);
2412                             }
2413                         }
2414                         
2415                         /* OK start to drive */
2416                         if (EXFAIL==_exproto_proto2ex(ndrx_G_view_field,  
2417                                     /* reduce the tag len.. header already read */
2418                                     (char *)(proto_buf+int_pos+tmpret), net_len-tmpret,
2419                                     /* Drive over internal variable + we should 
2420                                      * have callback when data completed, so that
2421                                      * we can install them in FB! */
2422                                     (char *)f, 0,
2423                                     max_struct, level,
2424                                     vdata, f, tmpf_len))
2425                         {
2426                             EXFAIL_OUT(ret);
2427                         }
2428                         
2429                         /**
2430                          * if there was master UBF present, then this
2431                          * is inner buffer... thus add the field.
2432                          * optimization: addfast
2433                          */
2434                         if (NULL!=p_typedbuf)
2435                         {
2436                             /* buf is current field offset */
2437                             if (EXSUCCEED!=Baddfast((UBFH *)p_typedbuf, p_ub_data->bfldid, 
2438                                     p_ub_data->buf, 0, &p_ub_data->next_fld))
2439                             {
2440                                 NDRX_LOG(log_error, "Failed to setup field %s:%s",
2441                                         Bfname(p_ub_data->bfldid), Bstrerror(Berror));
2442                                 ret=EXFAIL;
2443                                 goto out;
2444                             }
2445                         }
2446                         else
2447                         {
2448                             /* in master buffer we step by size of view + header */
2449                             *buf_len  = xatmi_fld_len = sizeof (ndrx_view_header) + f->v->ssize;
2450                             p_fld_len = &xatmi_fld_len;
2451                         }
2452                     }
2453                     else
2454                     {
2455                         
2456                         *buf_len = net_len;
2457                         NDRX_LOG(log_debug, "XATMIBUF - other type buffer, "
2458                                                 "just copy memory... (%u bytes)!", 
2459                                                 *buf_len);
2460                         /* Validate output buffer sizes */
2461                         
2462                         CHECK_EX_BUFSZ(ret, ex_offset, fld->offset, ex_bufsz, *buf_len);
2463                                 
2464                         /* Just copy off the memory & setup sizes (max offset) */
2465                         memcpy(data, (char *)(proto_buf+int_pos), *buf_len);
2466                         
2467                         xatmi_fld_len = *buf_len;
2468                         p_fld_len = &xatmi_fld_len;
2469                     }
2470                 }
2471                     break;
2472                 
2473                 default:
2474                     NDRX_LOG(log_error, "Unknown subfield type!");
2475                     ret=EXFAIL;
2476                     break;
2477             }
2478             
2479             /* Increase the max struct size... 
2480              */
2481             if (NULL==p_ub_data) /* Do not process in case if we have FB processing.! */
2482             {
2483                 /*
2484                 NDRX_LOG(log_debug, "I am here! %ld vs %ld", 
2485                                     fld->offset + ex_len + *p_fld_len, *max_struct);
2486                 */
2487                 if ((fld->offset + ex_offset + *p_fld_len) > *max_struct)
2488                 {
2489                     *max_struct = fld->offset +ex_offset+ *p_fld_len;
2490                     
2491                 }
2492             }
2493             
2494             if (NULL!=tmpf)
2495             {
2496                 
2497                 f=(proto_ufb_fld_t *)tmpf;
2498                 if (NULL!=f->vocc)
2499                 {
2500                     ndrx_viewocc_free(&f->vocc);
2501                 }
2502                 
2503                 NDRX_SYSBUF_FREE(tmpf);
2504                 tmpf=NULL;
2505             }
2506             
2507             /* terminate if requested so */
2508             if (fld->type & XFLAST)
2509             {
2510                 done=EXTRUE;
2511             }
2512             
2513         }
2514         /*
2515         NDRX_LOG(log_debug, "jump over: %hd", net_len);
2516         */
2517         int_pos+=net_len;
2518     }
2519     
2520 out:
2521     if (NULL!=tmpf)
2522     {
2523         /* free up  */
2524         f=(proto_ufb_fld_t *)tmpf;
2525         if (NULL!=f->vocc)
2526         {
2527             ndrx_viewocc_free(&f->vocc);
2528         }
2529 
2530         NDRX_SYSBUF_FREE(tmpf);
2531     }
2532 
2533     /* return the bytes processed... */
2534     if (EXFAIL!=ret)
2535     {
2536         ret=int_pos;
2537     }
2538 
2539     return ret;
2540 }
2541 
2542 
2543 /**
2544  * Classify the netcall message (return driver record).
2545  * @param ex_buf
2546  * @param ex_len
2547  * @return xmsg_t ptr or NULL
2548  */
2549 exprivate xmsg_t * classify_netcall (char *ex_buf, long ex_len)
2550 {
2551     xmsg_t *cv = M_ndrxd_x;
2552     cmd_br_net_call_t *msg = (cmd_br_net_call_t *)ex_buf;
2553     
2554     NDRX_LOG(log_debug, "%s: ex_buf: %p", __func__, ex_buf);
2555     /* OK, we should pick up the table and start to conv. */
2556     while (EXFAIL!=cv->command)
2557     {
2558         if ((msg->msg_type == cv->msg_type && msg->command_id == cv->command)
2559                 /* Accept any ATMI - common structure! */
2560                 || (msg->msg_type == cv->msg_type && 'A' == msg->msg_type))
2561         {
2562             NDRX_LOG(log_debug, "Found conv table for: %c/%d/%s", 
2563                     cv->msg_type, cv->command, cv->descr);
2564             
2565             return cv;
2566         }
2567         cv++;
2568     }
2569     
2570     NDRX_LOG(log_error, "No conv table for ndrxd command: %d"
2571             " - FAIL", cv->command);
2572     
2573     return NULL;
2574 }
2575 /* vim: set ts=4 sw=4 et smartindent: */